|
|
1.1 ! root 1: /* raw.c - implements raw ip 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: raw_rcv (struct sk_buff *skb, struct device *dev, struct options *opt, ! 51: unsigned long daddr, unsigned short len, unsigned long saddr, ! 52: int redo, struct ip_protocol *protocol) ! 53: { ! 54: ! 55: volatile struct sock *sk; ! 56: ! 57: sk = protocol->data; ! 58: ! 59: /* now we need to copy this into memory. */ ! 60: if (!redo ) ! 61: { ! 62: skb->dev = dev; ! 63: skb->saddr = daddr; ! 64: skb->daddr = saddr; ! 65: /* now see if we are in use. */ ! 66: cli(); ! 67: if (sk->inuse) ! 68: { ! 69: PRINTK ("raw_rcv adding to backlog. \n"); ! 70: if (sk->back_log == NULL) ! 71: { ! 72: sk->back_log = skb; ! 73: skb->next = skb; ! 74: skb->prev = skb; ! 75: } ! 76: else ! 77: { ! 78: skb->next = sk->back_log; ! 79: skb->prev = sk->back_log->prev; ! 80: skb->prev->next = skb; ! 81: skb->next->prev = skb; ! 82: } ! 83: sti(); ! 84: return (0); ! 85: } ! 86: sk->inuse = 1; ! 87: sti(); ! 88: } ! 89: ! 90: skb->sk = sk; ! 91: skb->len = len; ! 92: ! 93: /* charge it too the socket. */ ! 94: if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX) ! 95: { ! 96: skb->sk = NULL; ! 97: free_skb (skb, FREE_READ); ! 98: return (0); ! 99: } ! 100: ! 101: sk->rmem_alloc += skb->mem_len; ! 102: ! 103: /* now just put it onto the queue. */ ! 104: if (sk->rqueue == NULL) ! 105: { ! 106: sk->rqueue = skb; ! 107: skb->next = skb; ! 108: skb->prev = skb; ! 109: } ! 110: else ! 111: { ! 112: skb->next = sk->rqueue; ! 113: skb->prev = sk->rqueue->prev; ! 114: skb->prev->next = skb; ! 115: skb->next->prev = skb; ! 116: } ! 117: skb->len = len; ! 118: wake_up (sk->sleep); ! 119: release_sock (sk); ! 120: return (0); ! 121: } ! 122: ! 123: static int ! 124: raw_loopback (volatile struct sock *sk, int prot, char *from, int len, ! 125: unsigned long daddr) ! 126: { ! 127: /* just pretend it just came in. */ ! 128: struct sk_buff *skb; ! 129: int err; ! 130: skb = malloc (len+sizeof (*skb)); ! 131: if (skb == NULL) return (-ENOMEM); ! 132: ! 133: skb->mem_addr = skb; ! 134: skb->mem_len = len + sizeof (*skb); ! 135: skb->h.raw = (unsigned char *)(skb+1); ! 136: verify_area (from, len); ! 137: memcpy_fromfs (skb+1, from, len); ! 138: err = raw_rcv (skb, NULL, NULL, daddr, len, sk->saddr, prot, 0); ! 139: return (err); ! 140: } ! 141: ! 142: /* this will do terrible things if len + ipheader + devheader > dev->mtu */ ! 143: static int ! 144: raw_sendto (volatile struct sock *sk, unsigned char *from, int len, ! 145: int noblock, ! 146: unsigned flags, struct sockaddr_in *usin, int addr_len) ! 147: { ! 148: struct sk_buff *skb; ! 149: struct device *dev=NULL; ! 150: struct sockaddr_in sin; ! 151: int tmp; ! 152: ! 153: /* check the flags. */ ! 154: if (flags) return (-EINVAL); ! 155: if (len < 0) return (-EINVAL); ! 156: ! 157: /* get and verify the address. */ ! 158: if (usin) ! 159: { ! 160: if (addr_len < sizeof (sin)) ! 161: return (-EINVAL); ! 162: verify_area (usin, sizeof (sin)); ! 163: memcpy_fromfs (&sin, usin, sizeof(sin)); ! 164: if (sin.sin_family && ! 165: sin.sin_family != AF_INET) ! 166: return (-EINVAL); ! 167: } ! 168: else ! 169: { ! 170: if (sk->state != TCP_ESTABLISHED) ! 171: return (-EINVAL); ! 172: sin.sin_family = AF_INET; ! 173: sin.sin_port = sk->protocol; ! 174: sin.sin_addr.s_addr = sk->daddr; ! 175: } ! 176: if (sin.sin_port == 0) sin.sin_port = sk->protocol; ! 177: ! 178: if ((sin.sin_addr.s_addr & 0xff000000) == 0) ! 179: { ! 180: int err; ! 181: err = raw_loopback (sk, sin.sin_port, from, len, ! 182: sin.sin_addr.s_addr); ! 183: if (err < 0) return (err); ! 184: } ! 185: ! 186: sk->inuse = 1; ! 187: skb = sk->prot->wmalloc (sk, len+sizeof (*skb) + sk->prot->max_header, 0); ! 188: /* this shouldn't happen, but it could. */ ! 189: if (skb == NULL) ! 190: { ! 191: PRINTK ("raw_sendto: write buffer full?\n"); ! 192: print_sk (sk); ! 193: release_sock (sk); ! 194: return (-EAGAIN); ! 195: } ! 196: skb->mem_addr = skb; ! 197: skb->mem_len = len + sizeof (*skb) +sk->prot->max_header; ! 198: skb->sk = sk; ! 199: skb->free = 1; /* these two should be unecessary. */ ! 200: skb->arp = 0; ! 201: tmp = sk->prot->build_header (skb, sk->saddr, ! 202: sin.sin_addr.s_addr, &dev, ! 203: sk->protocol, sk->opt, skb->mem_len); ! 204: if (tmp < 0) ! 205: { ! 206: sk->prot->wfree (sk, skb->mem_addr, skb->mem_len); ! 207: release_sock (sk); ! 208: return (tmp); ! 209: } ! 210: verify_area (from, len); ! 211: memcpy_fromfs (skb+1, from, len); ! 212: skb->len = tmp + len; ! 213: sk->prot->queue_xmit (sk, dev, skb, 1); ! 214: return (len); ! 215: } ! 216: ! 217: static int ! 218: raw_write (volatile struct sock *sk, unsigned char *buff, int len, int noblock, ! 219: unsigned flags) ! 220: { ! 221: return (raw_sendto (sk, buff, len, noblock, flags, NULL, 0)); ! 222: } ! 223: ! 224: static void ! 225: raw_close (volatile struct sock *sk, int timeout) ! 226: { ! 227: sk->inuse = 1; ! 228: sk->state = TCP_CLOSE; ! 229: delete_ip_protocol ((struct ip_protocol *)sk->pair); ! 230: free_s ((void *)sk->pair, sizeof (struct ip_protocol)); ! 231: release_sock (sk); ! 232: } ! 233: ! 234: static int ! 235: raw_init (volatile struct sock *sk) ! 236: { ! 237: struct ip_protocol *p; ! 238: p = malloc (sizeof (*p)); ! 239: if (p == NULL) return (-ENOMEM); ! 240: ! 241: p->handler = raw_rcv; ! 242: p->protocol = sk->protocol; ! 243: p->data = (void *)sk; ! 244: add_ip_protocol (p); ! 245: ! 246: /* we need to remember this somewhere. */ ! 247: sk->pair = (volatile struct sock *)p; ! 248: ! 249: return (0); ! 250: } ! 251: ! 252: ! 253: int ! 254: raw_recvfrom (volatile struct sock *sk, unsigned char *to, int len, ! 255: int noblock, ! 256: unsigned flags, struct sockaddr_in *sin, int *addr_len) ! 257: { ! 258: /* this should be easy, if there is something there we ! 259: return it, otherwise we block. */ ! 260: int copied=0; ! 261: struct sk_buff *skb; ! 262: if (len == 0) return (0); ! 263: if (len < 0) return (-EINVAL); ! 264: if (addr_len) ! 265: { ! 266: verify_area (addr_len, sizeof(*addr_len)); ! 267: put_fs_long (sizeof (*sin), addr_len); ! 268: } ! 269: sk->inuse = 1; ! 270: while (sk->rqueue == NULL) ! 271: { ! 272: if (noblock) ! 273: { ! 274: release_sock (sk); ! 275: return (-EAGAIN); ! 276: } ! 277: release_sock (sk); ! 278: cli(); ! 279: if (sk->rqueue == NULL) ! 280: { ! 281: interruptible_sleep_on (sk->sleep); ! 282: if (current->signal & ~current->blocked) ! 283: { ! 284: return (-ERESTARTSYS); ! 285: } ! 286: } ! 287: sti(); ! 288: } ! 289: skb = sk->rqueue; ! 290: ! 291: if (!(flags & MSG_PEEK)) ! 292: { ! 293: if (skb->next == skb ) ! 294: { ! 295: sk->rqueue = NULL; ! 296: } ! 297: else ! 298: { ! 299: sk->rqueue = sk->rqueue ->next; ! 300: skb->prev->next = skb->next; ! 301: skb->next->prev = skb->prev; ! 302: } ! 303: } ! 304: copied = min (len, skb->len); ! 305: verify_area (to, copied); ! 306: memcpy_tofs (to, skb->h.raw, copied); ! 307: /* copy the address. */ ! 308: if (sin) ! 309: { ! 310: struct sockaddr_in addr; ! 311: addr.sin_family = AF_INET; ! 312: addr.sin_addr.s_addr = skb->daddr; ! 313: verify_area (sin, sizeof (*sin)); ! 314: memcpy_tofs(sin, &addr, sizeof (*sin)); ! 315: } ! 316: ! 317: if (!(flags & MSG_PEEK)) ! 318: { ! 319: free_skb (skb, FREE_READ); ! 320: } ! 321: release_sock (sk); ! 322: return (copied); ! 323: ! 324: } ! 325: ! 326: int ! 327: raw_read (volatile struct sock *sk, unsigned char *buff, int len, int noblock, ! 328: unsigned flags) ! 329: { ! 330: return (raw_recvfrom (sk, buff, len, noblock, flags, NULL, NULL)); ! 331: } ! 332: ! 333: ! 334: int udp_connect (volatile struct sock *sk, struct sockaddr_in *usin, ! 335: int addr_len); ! 336: ! 337: int udp_select (volatile struct sock *sk, int sel_type, select_table *wait); ! 338: ! 339: ! 340: struct proto raw_prot = ! 341: { ! 342: sock_wmalloc, ! 343: sock_rmalloc, ! 344: sock_wfree, ! 345: sock_rfree, ! 346: sock_rspace, ! 347: sock_wspace, ! 348: raw_close, ! 349: raw_read, ! 350: raw_write, ! 351: raw_sendto, ! 352: raw_recvfrom, ! 353: ip_build_header, ! 354: udp_connect, ! 355: NULL, ! 356: ip_queue_xmit, ! 357: ip_retransmit, ! 358: NULL, ! 359: NULL, ! 360: raw_rcv, ! 361: udp_select, ! 362: NULL, ! 363: raw_init, ! 364: 128, ! 365: 0, ! 366: {NULL,} ! 367: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.