|
|
1.1 ! root 1: /* packet.c - implements raw packet sockets. */ ! 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/sched.h> ! 25: #include <linux/fcntl.h> ! 26: #include <linux/socket.h> ! 27: #include <netinet/in.h> ! 28: #include "timer.h" ! 29: #include "ip.h" ! 30: #include "tcp.h" ! 31: #include "sock.h" ! 32: #include <linux/errno.h> ! 33: #include <linux/timer.h> ! 34: #include <asm/system.h> ! 35: #include <asm/segment.h> ! 36: #include "../kern_sock.h" /* for PRINTK */ ! 37: ! 38: extern struct proto raw_prot; ! 39: ! 40: static unsigned long ! 41: min(unsigned long a, unsigned long b) ! 42: { ! 43: if (a < b) return (a); ! 44: return (b); ! 45: } ! 46: ! 47: /* this should be the easiest of all, all we do is copy it into ! 48: a buffer. */ ! 49: int ! 50: packet_rcv (struct sk_buff *skb, struct device *dev, struct packet_type *pt) ! 51: { ! 52: volatile struct sock *sk; ! 53: ! 54: sk = pt->data; ! 55: skb->dev = dev; ! 56: skb->len += dev->hard_header_len; ! 57: ! 58: /* now see if we are in use. */ ! 59: cli(); ! 60: if (sk->inuse) ! 61: { ! 62: sti(); ! 63: /* drop any packets if we can't currently deal with them. ! 64: Assume that the other end will retransmit if it was ! 65: important. */ ! 66: skb->sk = NULL; ! 67: free_skb (skb, FREE_READ); ! 68: return (0); ! 69: ! 70: } ! 71: sk->inuse = 1; ! 72: sti (); ! 73: ! 74: skb->sk = sk; ! 75: ! 76: /* charge it too the socket. */ ! 77: if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX) ! 78: { ! 79: skb->sk = NULL; ! 80: free_skb (skb, FREE_READ); ! 81: return (0); ! 82: } ! 83: ! 84: sk->rmem_alloc += skb->mem_len; ! 85: ! 86: /* now just put it onto the queue. */ ! 87: if (sk->rqueue == NULL) ! 88: { ! 89: sk->rqueue = skb; ! 90: skb->next = skb; ! 91: skb->prev = skb; ! 92: } ! 93: else ! 94: { ! 95: skb->next = sk->rqueue; ! 96: skb->prev = sk->rqueue->prev; ! 97: skb->prev->next = skb; ! 98: skb->next->prev = skb; ! 99: } ! 100: wake_up (sk->sleep); ! 101: release_sock (sk); ! 102: return (0); ! 103: } ! 104: ! 105: /* this will do terrible things if len + ipheader + devheader > dev->mtu */ ! 106: static int ! 107: packet_sendto (volatile struct sock *sk, unsigned char *from, int len, ! 108: int noblock, ! 109: unsigned flags, struct sockaddr_in *usin, int addr_len) ! 110: { ! 111: struct sk_buff *skb; ! 112: struct device *dev; ! 113: struct sockaddr saddr; ! 114: ! 115: /* check the flags. */ ! 116: if (flags) return (-EINVAL); ! 117: if (len < 0) return (-EINVAL); ! 118: ! 119: /* get and verify the address. */ ! 120: if (usin) ! 121: { ! 122: if (addr_len < sizeof (saddr)) ! 123: return (-EINVAL); ! 124: verify_area (usin, sizeof (saddr)); ! 125: memcpy_fromfs (&saddr, usin, sizeof(saddr)); ! 126: } ! 127: else ! 128: return (-EINVAL); ! 129: ! 130: skb = sk->prot->wmalloc (sk, len+sizeof (*skb) + sk->prot->max_header, 0); ! 131: /* this shouldn't happen, but it could. */ ! 132: if (skb == NULL) ! 133: { ! 134: PRINTK ("packet_sendto: write buffer full?\n"); ! 135: print_sk (sk); ! 136: return (-EAGAIN); ! 137: } ! 138: skb->mem_addr = skb; ! 139: skb->mem_len = len + sizeof (*skb) +sk->prot->max_header; ! 140: skb->sk = sk; ! 141: skb->free = 1; ! 142: saddr.sa_data[13] = 0; ! 143: dev = get_dev (saddr.sa_data); ! 144: if (dev == NULL) ! 145: { ! 146: sk->prot->wfree (sk, skb->mem_addr, skb->mem_len); ! 147: return (-ENXIO); ! 148: } ! 149: verify_area (from, len); ! 150: memcpy_fromfs (skb+1, from, len); ! 151: skb->len = len; ! 152: skb->next = NULL; ! 153: if (dev->up) ! 154: dev->queue_xmit (skb, dev, sk->priority); ! 155: else ! 156: free_skb (skb, FREE_WRITE); ! 157: return (len); ! 158: } ! 159: ! 160: static int ! 161: packet_write (volatile struct sock *sk, unsigned char *buff, ! 162: int len, int noblock, unsigned flags) ! 163: { ! 164: return (packet_sendto (sk, buff, len, noblock, flags, NULL, 0)); ! 165: } ! 166: ! 167: static void ! 168: packet_close (volatile struct sock *sk, int timeout) ! 169: { ! 170: sk->inuse = 1; ! 171: sk->state = TCP_CLOSE; ! 172: dev_remove_pack ((struct packet_type *)sk->pair); ! 173: free_s ((void *)sk->pair, sizeof (struct packet_type)); ! 174: release_sock (sk); ! 175: } ! 176: ! 177: static int ! 178: packet_init (volatile struct sock *sk) ! 179: { ! 180: struct packet_type *p; ! 181: p = malloc (sizeof (*p)); ! 182: if (p == NULL) return (-ENOMEM); ! 183: ! 184: p->func = packet_rcv; ! 185: p->type = sk->num; ! 186: p->data = (void *)sk; ! 187: dev_add_pack (p); ! 188: ! 189: /* we need to remember this somewhere. */ ! 190: sk->pair = (volatile struct sock *)p; ! 191: ! 192: return (0); ! 193: } ! 194: ! 195: ! 196: int ! 197: packet_recvfrom (volatile struct sock *sk, unsigned char *to, int len, ! 198: int noblock, ! 199: unsigned flags, struct sockaddr_in *sin, int *addr_len) ! 200: { ! 201: /* this should be easy, if there is something there we ! 202: return it, otherwise we block. */ ! 203: int copied=0; ! 204: struct sk_buff *skb; ! 205: struct sockaddr *saddr; ! 206: saddr = (struct sockaddr *)sin; ! 207: ! 208: if (len == 0) return (0); ! 209: if (len < 0) return (-EINVAL); ! 210: if (addr_len) ! 211: { ! 212: verify_area (addr_len, sizeof(*addr_len)); ! 213: put_fs_long (sizeof (*saddr), addr_len); ! 214: } ! 215: ! 216: sk->inuse = 1; ! 217: while (sk->rqueue == NULL) ! 218: { ! 219: if (noblock) ! 220: { ! 221: release_sock (sk); ! 222: return (-EAGAIN); ! 223: } ! 224: release_sock (sk); ! 225: cli(); ! 226: if (sk->rqueue == NULL) ! 227: { ! 228: interruptible_sleep_on (sk->sleep); ! 229: if (current->signal & ~current->blocked) ! 230: { ! 231: return (-ERESTARTSYS); ! 232: } ! 233: } ! 234: sti(); ! 235: } ! 236: skb = sk->rqueue; ! 237: ! 238: if (!(flags & MSG_PEEK)) ! 239: { ! 240: if (skb->next == skb ) ! 241: { ! 242: sk->rqueue = NULL; ! 243: } ! 244: else ! 245: { ! 246: sk->rqueue = sk->rqueue ->next; ! 247: skb->prev->next = skb->next; ! 248: skb->next->prev = skb->prev; ! 249: } ! 250: } ! 251: copied = min (len, skb->len); ! 252: verify_area (to, copied); ! 253: memcpy_tofs (to, skb+1, copied); ! 254: /* copy the address. */ ! 255: if (saddr) ! 256: { ! 257: struct sockaddr addr; ! 258: addr.sa_family = skb->dev->type; ! 259: memcpy (addr.sa_data,skb->dev->name, 14); ! 260: verify_area (saddr, sizeof (*saddr)); ! 261: memcpy_tofs(saddr, &addr, sizeof (*saddr)); ! 262: } ! 263: ! 264: if (!(flags & MSG_PEEK)) ! 265: { ! 266: free_skb (skb, FREE_READ); ! 267: } ! 268: ! 269: release_sock (sk); ! 270: return (copied); ! 271: ! 272: } ! 273: ! 274: int ! 275: packet_read (volatile struct sock *sk, unsigned char *buff, ! 276: int len, int noblock, unsigned flags) ! 277: { ! 278: return (packet_recvfrom (sk, buff, len, noblock, flags, NULL, NULL)); ! 279: } ! 280: ! 281: ! 282: int udp_connect (volatile struct sock *sk, struct sockaddr_in *usin, ! 283: int addr_len); ! 284: ! 285: int udp_select (volatile struct sock *sk, int sel_type, select_table *wait); ! 286: ! 287: ! 288: struct proto packet_prot = ! 289: { ! 290: sock_wmalloc, ! 291: sock_rmalloc, ! 292: sock_wfree, ! 293: sock_rfree, ! 294: sock_rspace, ! 295: sock_wspace, ! 296: packet_close, ! 297: packet_read, ! 298: packet_write, ! 299: packet_sendto, ! 300: packet_recvfrom, ! 301: ip_build_header, ! 302: udp_connect, ! 303: NULL, ! 304: ip_queue_xmit, ! 305: ip_retransmit, ! 306: NULL, ! 307: NULL, ! 308: NULL, ! 309: udp_select, ! 310: NULL, ! 311: packet_init, ! 312: 128, ! 313: 0, ! 314: {NULL,} ! 315: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.