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