0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <net/llc.h>
0016 #include <net/llc_if.h>
0017 #include <net/llc_conn.h>
0018 #include <net/llc_pdu.h>
0019 #include <net/llc_sap.h>
0020 #include <net/llc_s_ac.h>
0021 #include <net/llc_s_ev.h>
0022 #include <net/llc_s_st.h>
0023 #include <net/sock.h>
0024 #include <net/tcp_states.h>
0025 #include <linux/llc.h>
0026 #include <linux/slab.h>
0027
0028 static int llc_mac_header_len(unsigned short devtype)
0029 {
0030 switch (devtype) {
0031 case ARPHRD_ETHER:
0032 case ARPHRD_LOOPBACK:
0033 return sizeof(struct ethhdr);
0034 }
0035 return 0;
0036 }
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev,
0049 u8 type, u32 data_size)
0050 {
0051 int hlen = type == LLC_PDU_TYPE_U ? 3 : 4;
0052 struct sk_buff *skb;
0053
0054 hlen += llc_mac_header_len(dev->type);
0055 skb = alloc_skb(hlen + data_size, GFP_ATOMIC);
0056
0057 if (skb) {
0058 skb_reset_mac_header(skb);
0059 skb_reserve(skb, hlen);
0060 skb_reset_network_header(skb);
0061 skb_reset_transport_header(skb);
0062 skb->protocol = htons(ETH_P_802_2);
0063 skb->dev = dev;
0064 if (sk != NULL)
0065 skb_set_owner_w(skb, sk);
0066 }
0067 return skb;
0068 }
0069
0070 void llc_save_primitive(struct sock *sk, struct sk_buff *skb, u8 prim)
0071 {
0072 struct sockaddr_llc *addr;
0073
0074
0075 addr = llc_ui_skb_cb(skb);
0076
0077 memset(addr, 0, sizeof(*addr));
0078 addr->sllc_family = sk->sk_family;
0079 addr->sllc_arphrd = skb->dev->type;
0080 addr->sllc_test = prim == LLC_TEST_PRIM;
0081 addr->sllc_xid = prim == LLC_XID_PRIM;
0082 addr->sllc_ua = prim == LLC_DATAUNIT_PRIM;
0083 llc_pdu_decode_sa(skb, addr->sllc_mac);
0084 llc_pdu_decode_ssap(skb, &addr->sllc_sap);
0085 }
0086
0087
0088
0089
0090
0091
0092 void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb)
0093 {
0094 struct llc_sap_state_ev *ev = llc_sap_ev(skb);
0095 struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
0096
0097 switch (LLC_U_PDU_RSP(pdu)) {
0098 case LLC_1_PDU_CMD_TEST:
0099 ev->prim = LLC_TEST_PRIM; break;
0100 case LLC_1_PDU_CMD_XID:
0101 ev->prim = LLC_XID_PRIM; break;
0102 case LLC_1_PDU_CMD_UI:
0103 ev->prim = LLC_DATAUNIT_PRIM; break;
0104 }
0105 ev->ind_cfm_flag = LLC_IND;
0106 }
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117 static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap,
0118 struct sk_buff *skb)
0119 {
0120 int i = 0;
0121 struct llc_sap_state_trans *rc = NULL;
0122 struct llc_sap_state_trans **next_trans;
0123 struct llc_sap_state *curr_state = &llc_sap_state_table[sap->state - 1];
0124
0125
0126
0127
0128 for (next_trans = curr_state->transitions; next_trans[i]->ev; i++)
0129 if (!next_trans[i]->ev(sap, skb)) {
0130 rc = next_trans[i];
0131 break;
0132 }
0133 return rc;
0134 }
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 static int llc_exec_sap_trans_actions(struct llc_sap *sap,
0146 struct llc_sap_state_trans *trans,
0147 struct sk_buff *skb)
0148 {
0149 int rc = 0;
0150 const llc_sap_action_t *next_action = trans->ev_actions;
0151
0152 for (; next_action && *next_action; next_action++)
0153 if ((*next_action)(sap, skb))
0154 rc = 1;
0155 return rc;
0156 }
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167 static int llc_sap_next_state(struct llc_sap *sap, struct sk_buff *skb)
0168 {
0169 int rc = 1;
0170 struct llc_sap_state_trans *trans;
0171
0172 if (sap->state > LLC_NR_SAP_STATES)
0173 goto out;
0174 trans = llc_find_sap_trans(sap, skb);
0175 if (!trans)
0176 goto out;
0177
0178
0179
0180
0181
0182 rc = llc_exec_sap_trans_actions(sap, trans, skb);
0183 if (rc)
0184 goto out;
0185
0186
0187
0188 sap->state = trans->next_state;
0189 out:
0190 return rc;
0191 }
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204 static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
0205 {
0206 struct llc_sap_state_ev *ev = llc_sap_ev(skb);
0207
0208 ev->ind_cfm_flag = 0;
0209 llc_sap_next_state(sap, skb);
0210
0211 if (ev->ind_cfm_flag == LLC_IND && skb->sk->sk_state != TCP_LISTEN) {
0212 llc_save_primitive(skb->sk, skb, ev->prim);
0213
0214
0215 if (sock_queue_rcv_skb(skb->sk, skb) == 0)
0216 return;
0217 }
0218 kfree_skb(skb);
0219 }
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231 void llc_build_and_send_test_pkt(struct llc_sap *sap,
0232 struct sk_buff *skb, u8 *dmac, u8 dsap)
0233 {
0234 struct llc_sap_state_ev *ev = llc_sap_ev(skb);
0235
0236 ev->saddr.lsap = sap->laddr.lsap;
0237 ev->daddr.lsap = dsap;
0238 memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
0239 memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
0240
0241 ev->type = LLC_SAP_EV_TYPE_PRIM;
0242 ev->prim = LLC_TEST_PRIM;
0243 ev->prim_type = LLC_PRIM_TYPE_REQ;
0244 llc_sap_state_process(sap, skb);
0245 }
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
0258 u8 *dmac, u8 dsap)
0259 {
0260 struct llc_sap_state_ev *ev = llc_sap_ev(skb);
0261
0262 ev->saddr.lsap = sap->laddr.lsap;
0263 ev->daddr.lsap = dsap;
0264 memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
0265 memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
0266
0267 ev->type = LLC_SAP_EV_TYPE_PRIM;
0268 ev->prim = LLC_XID_PRIM;
0269 ev->prim_type = LLC_PRIM_TYPE_REQ;
0270 llc_sap_state_process(sap, skb);
0271 }
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281 static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb,
0282 struct sock *sk)
0283 {
0284 struct llc_sap_state_ev *ev = llc_sap_ev(skb);
0285
0286 ev->type = LLC_SAP_EV_TYPE_PDU;
0287 ev->reason = 0;
0288 skb_orphan(skb);
0289 sock_hold(sk);
0290 skb->sk = sk;
0291 skb->destructor = sock_efree;
0292 llc_sap_state_process(sap, skb);
0293 }
0294
0295 static inline bool llc_dgram_match(const struct llc_sap *sap,
0296 const struct llc_addr *laddr,
0297 const struct sock *sk)
0298 {
0299 struct llc_sock *llc = llc_sk(sk);
0300
0301 return sk->sk_type == SOCK_DGRAM &&
0302 llc->laddr.lsap == laddr->lsap &&
0303 ether_addr_equal(llc->laddr.mac, laddr->mac);
0304 }
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314 static struct sock *llc_lookup_dgram(struct llc_sap *sap,
0315 const struct llc_addr *laddr)
0316 {
0317 struct sock *rc;
0318 struct hlist_nulls_node *node;
0319 int slot = llc_sk_laddr_hashfn(sap, laddr);
0320 struct hlist_nulls_head *laddr_hb = &sap->sk_laddr_hash[slot];
0321
0322 rcu_read_lock_bh();
0323 again:
0324 sk_nulls_for_each_rcu(rc, node, laddr_hb) {
0325 if (llc_dgram_match(sap, laddr, rc)) {
0326
0327 if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
0328 goto again;
0329 if (unlikely(llc_sk(rc)->sap != sap ||
0330 !llc_dgram_match(sap, laddr, rc))) {
0331 sock_put(rc);
0332 continue;
0333 }
0334 goto found;
0335 }
0336 }
0337 rc = NULL;
0338
0339
0340
0341
0342
0343 if (unlikely(get_nulls_value(node) != slot))
0344 goto again;
0345 found:
0346 rcu_read_unlock_bh();
0347 return rc;
0348 }
0349
0350 static inline bool llc_mcast_match(const struct llc_sap *sap,
0351 const struct llc_addr *laddr,
0352 const struct sk_buff *skb,
0353 const struct sock *sk)
0354 {
0355 struct llc_sock *llc = llc_sk(sk);
0356
0357 return sk->sk_type == SOCK_DGRAM &&
0358 llc->laddr.lsap == laddr->lsap &&
0359 llc->dev == skb->dev;
0360 }
0361
0362 static void llc_do_mcast(struct llc_sap *sap, struct sk_buff *skb,
0363 struct sock **stack, int count)
0364 {
0365 struct sk_buff *skb1;
0366 int i;
0367
0368 for (i = 0; i < count; i++) {
0369 skb1 = skb_clone(skb, GFP_ATOMIC);
0370 if (!skb1) {
0371 sock_put(stack[i]);
0372 continue;
0373 }
0374
0375 llc_sap_rcv(sap, skb1, stack[i]);
0376 sock_put(stack[i]);
0377 }
0378 }
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389 static void llc_sap_mcast(struct llc_sap *sap,
0390 const struct llc_addr *laddr,
0391 struct sk_buff *skb)
0392 {
0393 int i = 0;
0394 struct sock *sk;
0395 struct sock *stack[256 / sizeof(struct sock *)];
0396 struct llc_sock *llc;
0397 struct hlist_head *dev_hb = llc_sk_dev_hash(sap, skb->dev->ifindex);
0398
0399 spin_lock_bh(&sap->sk_lock);
0400 hlist_for_each_entry(llc, dev_hb, dev_hash_node) {
0401
0402 sk = &llc->sk;
0403
0404 if (!llc_mcast_match(sap, laddr, skb, sk))
0405 continue;
0406
0407 sock_hold(sk);
0408 if (i < ARRAY_SIZE(stack))
0409 stack[i++] = sk;
0410 else {
0411 llc_do_mcast(sap, skb, stack, i);
0412 i = 0;
0413 }
0414 }
0415 spin_unlock_bh(&sap->sk_lock);
0416
0417 llc_do_mcast(sap, skb, stack, i);
0418 }
0419
0420
0421 void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
0422 {
0423 struct llc_addr laddr;
0424
0425 llc_pdu_decode_da(skb, laddr.mac);
0426 llc_pdu_decode_dsap(skb, &laddr.lsap);
0427
0428 if (is_multicast_ether_addr(laddr.mac)) {
0429 llc_sap_mcast(sap, &laddr, skb);
0430 kfree_skb(skb);
0431 } else {
0432 struct sock *sk = llc_lookup_dgram(sap, &laddr);
0433 if (sk) {
0434 llc_sap_rcv(sap, skb, sk);
0435 sock_put(sk);
0436 } else
0437 kfree_skb(skb);
0438 }
0439 }