[PPPOE]: Key connections properly on local device.

It is based on the assumption that an interface's ifindex is basically
an alias for a local MAC address, so incoming packets now are matched
to sockets based on remote MAC, session id, and ifindex of the
interface the packet came in on/the socket was bound to by connect().

For relayed packets, the socket that's used for relaying is selected
based on destination MAC, session ID and the interface index of the
interface whose name currently matches the name requested by userspace
as the relaying source interface.

Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Florian Zumbiehl and committed by David S. Miller 90719dbe 248f0672

+32 -20
+32 -20
drivers/net/pppoe.c
··· 7 * 8 * Version: 0.7.0 9 * 10 * 220102 : Fix module use count on failure in pppoe_create, pppox_sk -acme 11 * 030700 : Fixed connect logic to allow for disconnect. 12 * 270700 : Fixed potential SMP problems; we must protect against ··· 133 * Set/get/delete/rehash items (internal versions) 134 * 135 **********************************************************************/ 136 - static struct pppox_sock *__get_item(unsigned long sid, unsigned char *addr) 137 { 138 int hash = hash_item(sid, addr); 139 struct pppox_sock *ret; 140 141 ret = item_hash_table[hash]; 142 143 - while (ret && !cmp_addr(&ret->pppoe_pa, sid, addr)) 144 ret = ret->next; 145 146 return ret; ··· 153 154 ret = item_hash_table[hash]; 155 while (ret) { 156 - if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa)) 157 return -EALREADY; 158 159 ret = ret->next; 160 } 161 162 - if (!ret) { 163 - po->next = item_hash_table[hash]; 164 - item_hash_table[hash] = po; 165 - } 166 167 return 0; 168 } 169 170 - static struct pppox_sock *__delete_item(unsigned long sid, char *addr) 171 { 172 int hash = hash_item(sid, addr); 173 struct pppox_sock *ret, **src; ··· 174 src = &item_hash_table[hash]; 175 176 while (ret) { 177 - if (cmp_addr(&ret->pppoe_pa, sid, addr)) { 178 *src = ret->next; 179 break; 180 } ··· 192 * 193 **********************************************************************/ 194 static inline struct pppox_sock *get_item(unsigned long sid, 195 - unsigned char *addr) 196 { 197 struct pppox_sock *po; 198 199 read_lock_bh(&pppoe_hash_lock); 200 - po = __get_item(sid, addr); 201 if (po) 202 sock_hold(sk_pppox(po)); 203 read_unlock_bh(&pppoe_hash_lock); ··· 207 208 static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp) 209 { 210 - return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote); 211 } 212 213 static inline int set_item(struct pppox_sock *po) ··· 232 return i; 233 } 234 235 - static inline struct pppox_sock *delete_item(unsigned long sid, char *addr) 236 { 237 struct pppox_sock *ret; 238 239 write_lock_bh(&pppoe_hash_lock); 240 - ret = __delete_item(sid, addr); 241 write_unlock_bh(&pppoe_hash_lock); 242 243 return ret; ··· 403 404 ph = (struct pppoe_hdr *) skb->nh.raw; 405 406 - po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); 407 if (po != NULL) 408 return sk_receive_skb(sk_pppox(po), skb, 0); 409 drop: ··· 437 if (ph->code != PADT_CODE) 438 goto abort; 439 440 - po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); 441 if (po) { 442 struct sock *sk = sk_pppox(po); 443 ··· 529 530 po = pppox_sk(sk); 531 if (po->pppoe_pa.sid) { 532 - delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote); 533 } 534 535 if (po->pppoe_dev) ··· 551 int sockaddr_len, int flags) 552 { 553 struct sock *sk = sock->sk; 554 - struct net_device *dev = NULL; 555 struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; 556 struct pppox_sock *po = pppox_sk(sk); 557 int error; ··· 577 pppox_unbind_sock(sk); 578 579 /* Delete the old binding */ 580 - delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote); 581 582 if(po->pppoe_dev) 583 dev_put(po->pppoe_dev); ··· 717 break; 718 719 /* PPPoE address from the user specifies an outbound 720 - PPPoE address to which frames are forwarded to */ 721 err = -EFAULT; 722 if (copy_from_user(&po->pppoe_relay, 723 (void __user *)arg,
··· 7 * 8 * Version: 0.7.0 9 * 10 + * 070228 : Fix to allow multiple sessions with same remote MAC and same 11 + * session id by including the local device ifindex in the 12 + * tuple identifying a session. This also ensures packets can't 13 + * be injected into a session from interfaces other than the one 14 + * specified by userspace. Florian Zumbiehl <florz@florz.de> 15 + * (Oh, BTW, this one is YYMMDD, in case you were wondering ...) 16 * 220102 : Fix module use count on failure in pppoe_create, pppox_sk -acme 17 * 030700 : Fixed connect logic to allow for disconnect. 18 * 270700 : Fixed potential SMP problems; we must protect against ··· 127 * Set/get/delete/rehash items (internal versions) 128 * 129 **********************************************************************/ 130 + static struct pppox_sock *__get_item(unsigned long sid, unsigned char *addr, int ifindex) 131 { 132 int hash = hash_item(sid, addr); 133 struct pppox_sock *ret; 134 135 ret = item_hash_table[hash]; 136 137 + while (ret && !(cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_dev->ifindex == ifindex)) 138 ret = ret->next; 139 140 return ret; ··· 147 148 ret = item_hash_table[hash]; 149 while (ret) { 150 + if (cmp_2_addr(&ret->pppoe_pa, &po->pppoe_pa) && ret->pppoe_dev->ifindex == po->pppoe_dev->ifindex) 151 return -EALREADY; 152 153 ret = ret->next; 154 } 155 156 + po->next = item_hash_table[hash]; 157 + item_hash_table[hash] = po; 158 159 return 0; 160 } 161 162 + static struct pppox_sock *__delete_item(unsigned long sid, char *addr, int ifindex) 163 { 164 int hash = hash_item(sid, addr); 165 struct pppox_sock *ret, **src; ··· 170 src = &item_hash_table[hash]; 171 172 while (ret) { 173 + if (cmp_addr(&ret->pppoe_pa, sid, addr) && ret->pppoe_dev->ifindex == ifindex) { 174 *src = ret->next; 175 break; 176 } ··· 188 * 189 **********************************************************************/ 190 static inline struct pppox_sock *get_item(unsigned long sid, 191 + unsigned char *addr, int ifindex) 192 { 193 struct pppox_sock *po; 194 195 read_lock_bh(&pppoe_hash_lock); 196 + po = __get_item(sid, addr, ifindex); 197 if (po) 198 sock_hold(sk_pppox(po)); 199 read_unlock_bh(&pppoe_hash_lock); ··· 203 204 static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp) 205 { 206 + struct net_device *dev = NULL; 207 + int ifindex; 208 + 209 + dev = dev_get_by_name(sp->sa_addr.pppoe.dev); 210 + if(!dev) 211 + return NULL; 212 + ifindex = dev->ifindex; 213 + dev_put(dev); 214 + return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote, ifindex); 215 } 216 217 static inline int set_item(struct pppox_sock *po) ··· 220 return i; 221 } 222 223 + static inline struct pppox_sock *delete_item(unsigned long sid, char *addr, int ifindex) 224 { 225 struct pppox_sock *ret; 226 227 write_lock_bh(&pppoe_hash_lock); 228 + ret = __delete_item(sid, addr, ifindex); 229 write_unlock_bh(&pppoe_hash_lock); 230 231 return ret; ··· 391 392 ph = (struct pppoe_hdr *) skb->nh.raw; 393 394 + po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source, dev->ifindex); 395 if (po != NULL) 396 return sk_receive_skb(sk_pppox(po), skb, 0); 397 drop: ··· 425 if (ph->code != PADT_CODE) 426 goto abort; 427 428 + po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source, dev->ifindex); 429 if (po) { 430 struct sock *sk = sk_pppox(po); 431 ··· 517 518 po = pppox_sk(sk); 519 if (po->pppoe_pa.sid) { 520 + delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote, po->pppoe_dev->ifindex); 521 } 522 523 if (po->pppoe_dev) ··· 539 int sockaddr_len, int flags) 540 { 541 struct sock *sk = sock->sk; 542 + struct net_device *dev; 543 struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; 544 struct pppox_sock *po = pppox_sk(sk); 545 int error; ··· 565 pppox_unbind_sock(sk); 566 567 /* Delete the old binding */ 568 + delete_item(po->pppoe_pa.sid,po->pppoe_pa.remote,po->pppoe_dev->ifindex); 569 570 if(po->pppoe_dev) 571 dev_put(po->pppoe_dev); ··· 705 break; 706 707 /* PPPoE address from the user specifies an outbound 708 + PPPoE address which frames are forwarded to */ 709 err = -EFAULT; 710 if (copy_from_user(&po->pppoe_relay, 711 (void __user *)arg,