|
|
1.1 ! root 1: /* arp.c */ ! 2: /* ! 3: Copyright (C) 1992 Ross Biro ! 4: ! 5: This program is free software; you can redistribute it and/or modify ! 6: it under the terms of the GNU General Public License as published by ! 7: the Free Software Foundation; either version 2, or (at your option) ! 8: any later version. ! 9: ! 10: This program is distributed in the hope that it will be useful, ! 11: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 13: GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with this program; if not, write to the Free Software ! 17: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 18: ! 19: The Author may be reached as [email protected] or ! 20: C/O Department of Mathematics; Stanford University; Stanford, CA 94305 ! 21: */ ! 22: ! 23: #include <linux/types.h> ! 24: #include <linux/string.h> ! 25: #include <linux/kernel.h> ! 26: #include <linux/sched.h> ! 27: ! 28: #include <linux/socket.h> ! 29: #include <netinet/in.h> ! 30: #include <asm/system.h> ! 31: ! 32: #include "timer.h" ! 33: #include "ip.h" ! 34: #include "tcp.h" ! 35: #include "sock.h" ! 36: #include "arp.h" ! 37: ! 38: #undef ARP_DEBUG ! 39: #ifdef ARP_DEBUG ! 40: #define PRINTK printk ! 41: #else ! 42: #define PRINTK dummy_routine ! 43: #endif ! 44: ! 45: static struct arp_table *arp_table[ARP_TABLE_SIZE] ={NULL, }; ! 46: static struct sk_buff *arp_q=NULL; ! 47: ! 48: /* this will try to retransmit everything on the queue. */ ! 49: static void ! 50: send_arp_q(void) ! 51: { ! 52: struct sk_buff *skb; ! 53: if (arp_q == NULL) return; ! 54: ! 55: skb = arp_q; ! 56: do { ! 57: if (!skb->dev->rebuild_header (skb+1, skb->dev)) ! 58: { ! 59: if (skb->next == skb) ! 60: { ! 61: arp_q = NULL; ! 62: } ! 63: else ! 64: { ! 65: skb->next->prev = skb->prev; ! 66: skb->prev->next = skb->next; ! 67: arp_q = skb->next; ! 68: } ! 69: skb->next = NULL; ! 70: skb->prev = NULL; ! 71: skb->arp = 1; ! 72: skb->dev->queue_xmit (skb, skb->dev, 0); ! 73: if (arp_q == NULL) break; ! 74: skb = arp_q; ! 75: continue; ! 76: } ! 77: skb=skb->next; ! 78: } while (skb != arp_q); ! 79: ! 80: } ! 81: ! 82: static void ! 83: print_arp(struct arp *arp) ! 84: { ! 85: int i; ! 86: unsigned long *lptr; ! 87: unsigned char *ptr; ! 88: PRINTK ("arp: \n"); ! 89: PRINTK (" hrd = %d\n",net16(arp->hrd)); ! 90: PRINTK (" pro = %d\n",net16(arp->pro)); ! 91: PRINTK (" hlen = %d plen = %d\n",arp->hlen, arp->plen); ! 92: PRINTK (" op = %d\n", net16(arp->op)); ! 93: ptr = (unsigned char *)(arp+1); ! 94: PRINTK (" sender haddr = "); ! 95: for (i = 0; i < arp->hlen; i++) ! 96: { ! 97: PRINTK ("0x%02X ",*ptr++); ! 98: } ! 99: lptr = (void *)ptr; ! 100: PRINTK (" send paddr = %X\n",*lptr); ! 101: lptr ++; ! 102: ptr = (void *)lptr; ! 103: PRINTK (" destination haddr = "); ! 104: for (i = 0; i < arp->hlen; i++) ! 105: { ! 106: PRINTK ("0x%02X ",*ptr++); ! 107: } ! 108: lptr = (void *)ptr; ! 109: PRINTK (" destination paddr = %X\n",*lptr); ! 110: } ! 111: ! 112: static unsigned char * ! 113: arp_sourceh(struct arp *arp) ! 114: { ! 115: unsigned char *ptr; ! 116: ptr = (unsigned char *)(arp + 1); ! 117: return (ptr); ! 118: } ! 119: ! 120: static unsigned char * ! 121: arp_targeth(struct arp *arp) ! 122: { ! 123: unsigned char *ptr; ! 124: ptr = (unsigned char *)(arp + 1); ! 125: ptr += arp->hlen+4; ! 126: return (ptr); ! 127: } ! 128: ! 129: static unsigned long * ! 130: arp_sourcep(struct arp *arp) ! 131: { ! 132: unsigned long *lptr; ! 133: unsigned char *ptr; ! 134: ptr = (unsigned char *)(arp + 1); ! 135: ptr += arp->hlen; ! 136: lptr = (unsigned long *)ptr; ! 137: return (lptr); ! 138: } ! 139: ! 140: ! 141: static unsigned long * ! 142: arp_targetp(struct arp *arp) ! 143: { ! 144: unsigned long *lptr; ! 145: unsigned char *ptr; ! 146: ptr = (unsigned char *)(arp + 1); ! 147: ptr += 2*arp->hlen+4; ! 148: lptr = (unsigned long *)ptr; ! 149: return (lptr); ! 150: } ! 151: ! 152: static void ! 153: arp_free (void *ptr, unsigned long len) ! 154: { ! 155: free_s(ptr, len); ! 156: } ! 157: ! 158: static void * ! 159: arp_malloc (unsigned long amount) ! 160: { ! 161: return (malloc (amount)); ! 162: } ! 163: ! 164: static int ! 165: arp_response (struct arp *arp1, struct device *dev) ! 166: { ! 167: struct arp *arp2; ! 168: struct sk_buff *skb; ! 169: int tmp; ! 170: ! 171: /* get some mem and initialize it for the return trip. */ ! 172: skb = arp_malloc (sizeof (*skb) + sizeof (*arp2) + ! 173: 2*arp1->hlen + 2*arp1->plen + dev->hard_header_len); ! 174: if (skb == NULL) return (1); ! 175: ! 176: skb->mem_addr = skb; ! 177: skb->mem_len = sizeof (*skb) + sizeof (*arp2) + 2*arp1->hlen + ! 178: 2*arp1->plen + dev->hard_header_len; ! 179: skb->len = sizeof (*arp2) + 2*arp1->hlen + ! 180: 2*arp1->plen + dev->hard_header_len; ! 181: ! 182: tmp = dev->hard_header((unsigned char *)(skb+1), dev, ! 183: ETHERTYPE_ARP, *arp_sourcep(arp1), ! 184: *arp_targetp(arp1),skb->len); ! 185: ! 186: if (tmp < 0) return (1); ! 187: ! 188: arp2 =(struct arp *) ((unsigned char *)skb+sizeof (*skb) + tmp ); ! 189: memcpy (arp2, arp1, sizeof (*arp2)); ! 190: ! 191: /* now swap the addresses. */ ! 192: *arp_sourcep(arp2) = *arp_targetp(arp1); ! 193: memcpy(arp_sourceh(arp2), dev->dev_addr, arp1->hlen); ! 194: ! 195: *arp_targetp(arp2) = *arp_sourcep(arp1); ! 196: memcpy(arp_targeth(arp2), arp_sourceh(arp1), arp1->hlen); ! 197: ! 198: arp2->op = NET16(ARP_REPLY); ! 199: skb->free = 1; ! 200: skb->arp = 1; /* so the code will know it's not waiting on an arp. */ ! 201: skb->sk = NULL; ! 202: skb->next = NULL; ! 203: PRINTK (">>"); ! 204: print_arp(arp2); ! 205: /* send it. */ ! 206: dev->queue_xmit (skb, dev, 0); ! 207: return (0); ! 208: } ! 209: ! 210: /* This will find an entry in the arp table by looking at the ip ! 211: address. */ ! 212: static struct arp_table * ! 213: arp_lookup (unsigned long paddr) ! 214: { ! 215: unsigned long hash; ! 216: struct arp_table *apt; ! 217: PRINTK ("arp_lookup(paddr=%X)\n", paddr); ! 218: /* we don't want to arp ourselves. */ ! 219: if (my_ip_addr(paddr)) return (NULL); ! 220: hash = net32(paddr) & (ARP_TABLE_SIZE - 1); ! 221: cli(); ! 222: for (apt = arp_table[hash]; apt != NULL; apt = apt->next) ! 223: { ! 224: if (apt->ip == paddr) ! 225: { ! 226: sti(); ! 227: return (apt); ! 228: } ! 229: } ! 230: sti(); ! 231: return (NULL); ! 232: } ! 233: ! 234: void ! 235: arp_destroy(unsigned long paddr) ! 236: { ! 237: unsigned long hash; ! 238: struct arp_table *apt; ! 239: struct arp_table *lapt; ! 240: PRINTK ("arp_destroy (paddr=%X)\n",paddr); ! 241: /* we don't want to destroy are own arp */ ! 242: if (my_ip_addr(paddr)) return; ! 243: hash = net32(paddr) & (ARP_TABLE_SIZE - 1); ! 244: ! 245: cli(); /* can't be interrupted. */ ! 246: /* make sure there is something there. */ ! 247: if (arp_table[hash] == NULL) return; ! 248: ! 249: /* check the first one. */ ! 250: if (arp_table[hash]->ip == paddr) ! 251: { ! 252: apt = arp_table[hash]; ! 253: arp_table[hash] = arp_table[hash]->next; ! 254: arp_free (apt, sizeof (*apt)); ! 255: sti(); ! 256: return; ! 257: } ! 258: ! 259: /* now deal with it any where else in the chain. */ ! 260: lapt = arp_table[hash]; ! 261: for (apt = arp_table[hash]->next; apt != NULL; apt = apt->next) ! 262: { ! 263: if (apt->ip == paddr) ! 264: { ! 265: lapt->next = apt->next; ! 266: arp_free (apt, sizeof (*apt)); ! 267: sti(); ! 268: return; ! 269: } ! 270: } ! 271: sti(); ! 272: } ! 273: ! 274: /* this routine does not check for duplicates. It assumes the caller ! 275: does. */ ! 276: static struct arp_table * ! 277: create_arp (unsigned long paddr, unsigned char *addr, int hlen) ! 278: { ! 279: struct arp_table *apt; ! 280: unsigned long hash; ! 281: apt = arp_malloc (sizeof (*apt)); ! 282: if (apt == NULL) return (NULL); ! 283: ! 284: hash = net32(paddr) & (ARP_TABLE_SIZE - 1); ! 285: apt->ip = paddr; ! 286: apt->hlen =hlen; ! 287: memcpy (apt->hard, addr, hlen); ! 288: apt->last_used=timer_seq; ! 289: sti(); ! 290: apt->next = arp_table[hash]; ! 291: arp_table[hash]=apt; ! 292: cli(); ! 293: return (apt); ! 294: } ! 295: ! 296: int ! 297: arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) ! 298: { ! 299: struct arp *arp; ! 300: struct arp_table *tbl; ! 301: int ret; ! 302: ! 303: PRINTK ("<<\n"); ! 304: arp = skb->h.arp; ! 305: print_arp(arp); ! 306: ! 307: /* if this test doesn't pass, something fishy is going on. */ ! 308: if (arp->hlen != dev->addr_len || dev->type !=NET16( arp->hrd)) ! 309: { ! 310: free_skb(skb, FREE_READ); ! 311: return (0); ! 312: } ! 313: ! 314: /* for now we will only deal with ip addresses. */ ! 315: if (arp->pro != NET16(ARP_IP_PROT) || arp->plen != 4) ! 316: { ! 317: free_skb (skb, FREE_READ); ! 318: return (0); ! 319: } ! 320: ! 321: /* now look up the ip address in the table. */ ! 322: tbl = arp_lookup (*arp_sourcep(arp)); ! 323: if (tbl != NULL) ! 324: { ! 325: memcpy (tbl->hard, arp+1, arp->hlen); ! 326: tbl->hlen = arp->hlen; ! 327: tbl->last_used = timer_seq; ! 328: } ! 329: ! 330: if (!my_ip_addr(*arp_targetp(arp))) ! 331: { ! 332: free_skb (skb, FREE_READ); ! 333: return (0); ! 334: } ! 335: ! 336: if (tbl == NULL) ! 337: create_arp (*arp_sourcep(arp), arp_sourceh(arp), arp->hlen); ! 338: ! 339: /* now see if we can send anything. */ ! 340: send_arp_q(); ! 341: ! 342: if (arp->op != NET16(ARP_REQUEST)) ! 343: { ! 344: free_skb (skb, FREE_READ); ! 345: return (0); ! 346: } ! 347: ! 348: /* now we need to create a new packet. */ ! 349: ret = arp_response(arp, dev); ! 350: free_skb (skb, FREE_READ); ! 351: return (ret); ! 352: } ! 353: ! 354: void ! 355: arp_snd (unsigned long paddr, struct device *dev, unsigned long saddr) ! 356: { ! 357: struct sk_buff *skb; ! 358: struct arp *arp; ! 359: struct arp_table *apt; ! 360: int tmp; ! 361: PRINTK ("arp_snd (paddr=%X, dev=%X, saddr=%X)\n",paddr, dev, saddr); ! 362: ! 363: /* first we build a dummy arp table entry. */ ! 364: apt = create_arp (paddr, NULL, 0); ! 365: if (apt == NULL) return; ! 366: ! 367: skb = arp_malloc (sizeof (*arp) + sizeof (*skb) + dev->hard_header_len + ! 368: 2*dev->addr_len+8); ! 369: if (skb == NULL) return; ! 370: ! 371: skb->sk = NULL; ! 372: skb->mem_addr = skb; ! 373: skb->mem_len = sizeof (*arp) + sizeof (*skb) + dev->hard_header_len + ! 374: 2*dev->addr_len+8; ! 375: skb->arp = 1; ! 376: skb->dev = dev; ! 377: skb->len = sizeof (*arp) + dev->hard_header_len + 2*dev->addr_len+8; ! 378: skb->next = NULL; ! 379: ! 380: tmp = dev->hard_header ((unsigned char *)(skb+1), dev, ! 381: ETHERTYPE_ARP, 0, saddr, skb->len); ! 382: if (tmp < 0) ! 383: { ! 384: arp_free (skb->mem_addr, skb->mem_len); ! 385: return; ! 386: } ! 387: ! 388: arp =(struct arp *) ((unsigned char *)skb+sizeof (*skb) + tmp ); ! 389: arp->hrd = net16(dev->type); ! 390: arp->pro = NET16(ARP_IP_PROT); ! 391: arp->hlen = dev->addr_len; ! 392: arp->plen = 4; ! 393: arp->op = NET16(ARP_REQUEST); ! 394: *arp_sourcep(arp) = saddr; ! 395: *arp_targetp(arp) = paddr; ! 396: memcpy (arp_sourceh(arp), dev->dev_addr, dev->addr_len); ! 397: memcpy (arp_targeth(arp), dev->broadcast, dev->addr_len); ! 398: PRINTK(">>\n"); ! 399: print_arp(arp); ! 400: dev->queue_xmit (skb, dev, 0); ! 401: } ! 402: ! 403: int ! 404: arp_find(unsigned char *haddr, unsigned long paddr, struct device *dev, ! 405: unsigned long saddr) ! 406: { ! 407: struct arp_table *apt; ! 408: PRINTK ("arp_find(haddr=%X, paddr=%X, dev=%X, saddr=%X)\n", ! 409: haddr, paddr, dev, saddr); ! 410: if (my_ip_addr (paddr)) ! 411: { ! 412: memcpy (haddr, dev->dev_addr, dev->addr_len); ! 413: return (0); ! 414: } ! 415: apt = arp_lookup (paddr); ! 416: if (apt != NULL) ! 417: { ! 418: /* make sure it's not too old. If it is too old, we will ! 419: just pretend we did not find it, and then arp_snd ! 420: will verify the address for us. */ ! 421: if (!before (apt->last_used, timer_seq+ARP_TIMEOUT) && ! 422: apt->hlen != 0) ! 423: { ! 424: apt->last_used=timer_seq; ! 425: memcpy (haddr, apt->hard, dev->addr_len); ! 426: return (0); ! 427: } ! 428: } ! 429: ! 430: /* if we didn't find an entry, we will try to ! 431: send an arp packet. */ ! 432: if (apt == NULL || after (timer_seq, apt->last_used+ARP_RES_TIME)) ! 433: arp_snd(paddr,dev,saddr); ! 434: ! 435: /* this assume haddr are atleast 4 bytes. ! 436: If this isn't true we can use a lookup ! 437: table, one for every dev. */ ! 438: *(unsigned long *)haddr = paddr; ! 439: return (1); ! 440: } ! 441: ! 442: ! 443: void ! 444: arp_add (unsigned long addr, unsigned char *haddr, struct device *dev) ! 445: { ! 446: struct arp_table *apt; ! 447: /* first see if the address is already in the table. */ ! 448: apt = arp_lookup (addr); ! 449: if (apt != NULL) ! 450: { ! 451: apt->last_used = timer_seq; ! 452: memcpy (apt->hard, haddr , dev->addr_len); ! 453: return; ! 454: } ! 455: create_arp (addr, haddr, dev->addr_len); ! 456: } ! 457: ! 458: void ! 459: arp_add_broad (unsigned long addr, struct device *dev) ! 460: { ! 461: arp_add (addr, dev->broadcast , dev); ! 462: } ! 463: ! 464: ! 465: void ! 466: arp_queue(struct sk_buff *skb) ! 467: { ! 468: cli(); ! 469: if (arp_q == NULL) ! 470: { ! 471: arp_q = skb; ! 472: skb->next = skb; ! 473: skb->prev = skb; ! 474: } ! 475: else ! 476: { ! 477: skb->next = arp_q; ! 478: skb->prev = arp_q->prev; ! 479: skb->next->prev = skb; ! 480: skb->prev->next = skb; ! 481: } ! 482: sti(); ! 483: ! 484: } ! 485:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.