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