root/net/inet/raw.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. min
  2. raw_err
  3. raw_rcv
  4. raw_sendto
  5. raw_write
  6. raw_close
  7. raw_init
  8. raw_recvfrom
  9. raw_read

   1 /*
   2  * INET         An implementation of the TCP/IP protocol suite for the LINUX
   3  *              operating system.  INET is implemented using the  BSD Socket
   4  *              interface as the means of communication with the user level.
   5  *
   6  *              RAW - implementation of IP "raw" sockets.
   7  *
   8  * Version:     @(#)raw.c       1.0.4   05/25/93
   9  *
  10  * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
  11  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12  *
  13  *              This program is free software; you can redistribute it and/or
  14  *              modify it under the terms of the GNU General Public License
  15  *              as published by the Free Software Foundation; either version
  16  *              2 of the License, or (at your option) any later version.
  17  */
  18 #include <asm/system.h>
  19 #include <asm/segment.h>
  20 #include <linux/types.h>
  21 #include <linux/sched.h>
  22 #include <linux/errno.h>
  23 #include <linux/timer.h>
  24 #include <linux/mm.h>
  25 #include <linux/kernel.h>
  26 #include <linux/fcntl.h>
  27 #include <linux/socket.h>
  28 #include <linux/in.h>
  29 #include "inet.h"
  30 #include "dev.h"
  31 #include "ip.h"
  32 #include "protocol.h"
  33 #include "tcp.h"
  34 #include "skbuff.h"
  35 #include "sock.h"
  36 #include "icmp.h"
  37 #include "udp.h"
  38 
  39 
  40 static unsigned long
  41 min(unsigned long a, unsigned long b)
     /* [previous][next][first][last][top][bottom][index][help] */
  42 {
  43   if (a < b) return(a);
  44   return(b);
  45 }
  46 
  47 
  48 /* raw_err gets called by the icmp module. */
  49 void
  50 raw_err (int err, unsigned char *header, unsigned long daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
  51          unsigned long saddr, struct inet_protocol *protocol)
  52 {
  53   struct sock *sk;
  54    
  55   DPRINTF((DBG_RAW, "raw_err(err=%d, hdr=%X, daddr=%X, saddr=%X, protocl=%X)\n",
  56                 err, header, daddr, saddr, protocol));
  57 
  58   if (protocol == NULL) return;
  59   sk = (struct sock *) protocol->data;
  60   if (sk == NULL) return;
  61 
  62   /* This is meaningless in raw sockets. */
  63   if (err & 0xff00 == (ICMP_SOURCE_QUENCH << 8)) {
  64         if (sk->cong_window > 1) sk->cong_window = sk->cong_window/2;
  65         return;
  66   }
  67 
  68   sk->err = icmp_err_convert[err & 0xff].errno;
  69 
  70   /* None of them are fatal for raw sockets. */
  71 #if 0
  72   if (icmp_err_convert[err & 0xff].fatal) {
  73         sk->prot->close(sk, 0);
  74   }
  75 #endif
  76   return;
  77 }
  78 
  79 
  80 /*
  81  * This should be the easiest of all, all we do is\
  82  * copy it into a buffer.
  83  */
  84 int
  85 raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
  86         unsigned long daddr, unsigned short len, unsigned long saddr,
  87         int redo, struct inet_protocol *protocol)
  88 {
  89   struct sock *sk;
  90 
  91   DPRINTF((DBG_RAW, "raw_rcv(skb=%X, dev=%X, opt=%X, daddr=%X,\n"
  92            "         len=%d, saddr=%X, redo=%d, protocol=%X)\n",
  93            skb, dev, opt, daddr, len, saddr, redo, protocol));
  94 
  95   if (skb == NULL) return(0);
  96   if (protocol == NULL) {
  97         kfree_skb(skb, FREE_READ);
  98         return(0);
  99   }
 100   sk = (struct sock *) protocol->data;
 101   if (sk == NULL) {
 102         kfree_skb(skb, FREE_READ);
 103         return(0);
 104   }
 105 
 106   /* Now we need to copy this into memory. */
 107   skb->sk = sk;
 108   skb->len = len;
 109   skb->dev = dev;
 110   skb->saddr = daddr;
 111   skb->daddr = saddr;
 112 
 113   if (!redo) {
 114         /* Now see if we are in use. */
 115         cli();
 116         if (sk->inuse) {
 117                 DPRINTF((DBG_RAW, "raw_rcv adding to backlog.\n"));
 118                 if (sk->back_log == NULL) {
 119                         sk->back_log = skb;
 120                         skb->next = skb;
 121                         skb->prev = skb;
 122                 } else {
 123                         skb->next = sk->back_log;
 124                         skb->prev = sk->back_log->prev;
 125                         skb->prev->next = skb;
 126                         skb->next->prev = skb;
 127                 }
 128                 sti();
 129                 return(0);
 130         }
 131         sk->inuse = 1;
 132         sti();
 133   }
 134 
 135   /* Charge it too the socket. */
 136   if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX) {
 137         skb->sk = NULL;
 138         kfree_skb(skb, FREE_READ);
 139         return(0);
 140   }
 141   sk->rmem_alloc += skb->mem_len;
 142 
 143   /* Now just put it onto the queue. */
 144   if (sk->rqueue == NULL) {
 145         sk->rqueue = skb;
 146         skb->next = skb;
 147         skb->prev = skb;
 148   } else {
 149         skb->next = sk->rqueue;
 150         skb->prev = sk->rqueue->prev;
 151         skb->prev->next = skb;
 152         skb->next->prev = skb;
 153   }
 154   wake_up(sk->sleep);
 155   release_sock(sk);
 156   return(0);
 157 }
 158 
 159 
 160 /* This will do terrible things if len + ipheader + devheader > dev->mtu */
 161 static int
 162 raw_sendto(struct sock *sk, unsigned char *from, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 163            int noblock,
 164            unsigned flags, struct sockaddr_in *usin, int addr_len)
 165 {
 166   struct sk_buff *skb;
 167   struct device *dev=NULL;
 168   struct sockaddr_in sin;
 169   int tmp;
 170 
 171   DPRINTF((DBG_RAW, "raw_sendto(sk=%X, from=%X, len=%d, noblock=%d, flags=%X,\n"
 172            "            usin=%X, addr_len = %d)\n", sk, from, len, noblock,
 173            flags, usin, addr_len));
 174 
 175   /* Check the flags. */
 176   if (flags) return(-EINVAL);
 177   if (len < 0) return(-EINVAL);
 178 
 179   /* Get and verify the address. */
 180   if (usin) {
 181         if (addr_len < sizeof(sin)) return(-EINVAL);
 182         /* verify_area (VERIFY_WRITE, usin, sizeof (sin));*/
 183         memcpy_fromfs(&sin, usin, sizeof(sin));
 184         if (sin.sin_family && sin.sin_family != AF_INET) return(-EINVAL);
 185   } else {
 186         if (sk->state != TCP_ESTABLISHED) return(-EINVAL);
 187         sin.sin_family = AF_INET;
 188         sin.sin_port = sk->protocol;
 189         sin.sin_addr.s_addr = sk->daddr;
 190   }
 191   if (sin.sin_port == 0) sin.sin_port = sk->protocol;
 192 
 193   sk->inuse = 1;
 194   skb = NULL;
 195   while (skb == NULL) {
 196         skb = (struct sk_buff *) sk->prot->wmalloc(sk,
 197                         len+sizeof(*skb) + sk->prot->max_header,
 198                         0, GFP_KERNEL);
 199         /* This shouldn't happen, but it could. */
 200         /* FIXME: need to change this to sleep. */
 201         if (skb == NULL) {
 202                 int tmp;
 203 
 204                 DPRINTF((DBG_RAW, "raw_sendto: write buffer full?\n"));
 205                 if (noblock) return(-EAGAIN);
 206                 tmp = sk->wmem_alloc;
 207                 release_sock(sk);
 208                 cli();
 209                 if (tmp <= sk->wmem_alloc) {
 210                         interruptible_sleep_on(sk->sleep);
 211                         if (current->signal & ~current->blocked) {
 212                                 sti();
 213                                 return(-ERESTARTSYS);
 214                         }
 215                 }
 216                 sk->inuse = 1;
 217                 sti();
 218         }
 219   }
 220   skb->lock = 0;
 221   skb->mem_addr = skb;
 222   skb->mem_len = len + sizeof(*skb) +sk->prot->max_header;
 223   skb->sk = sk;
 224 
 225   skb->free = 1; /* these two should be unecessary. */
 226   skb->arp = 0;
 227 
 228   tmp = sk->prot->build_header(skb, sk->saddr, 
 229                                sin.sin_addr.s_addr, &dev,
 230                                sk->protocol, sk->opt, skb->mem_len);
 231   if (tmp < 0) {
 232         DPRINTF((DBG_RAW, "raw_sendto: error building ip header.\n"));
 233         sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
 234         release_sock(sk);
 235         return(tmp);
 236   }
 237 
 238   /* verify_area(VERIFY_WRITE, from, len);*/
 239   memcpy_fromfs ((unsigned char *)(skb+1)+tmp, from, len);
 240 
 241   /* If we are using IPPROTO_RAW, we need to fill in the source address in
 242      the IP header */
 243 
 244   if(sk->protocol==IPPROTO_RAW) {
 245     unsigned char *buff;
 246     struct iphdr *iph;
 247 
 248     buff = (unsigned char *)(skb + 1);
 249     buff += tmp;
 250     iph = (struct iphdr *)buff;
 251     iph->saddr = sk->saddr;
 252   }
 253 
 254   skb->len = tmp + len;
 255   sk->prot->queue_xmit(sk, dev, skb, 1);
 256   release_sock(sk);
 257   return(len);
 258 }
 259 
 260 
 261 static int
 262 raw_write(struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 263            unsigned flags)
 264 {
 265   return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0));
 266 }
 267 
 268 
 269 static void
 270 raw_close(struct sock *sk, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272   sk->inuse = 1;
 273   sk->state = TCP_CLOSE;
 274 
 275   DPRINTF((DBG_RAW, "raw_close: deleting protocol %d\n",
 276            ((struct inet_protocol *)sk->pair)->protocol));
 277 
 278   if (inet_del_protocol((struct inet_protocol *)sk->pair) < 0)
 279                 DPRINTF((DBG_RAW, "raw_close: del_protocol failed.\n"));
 280   kfree_s((void *)sk->pair, sizeof (struct inet_protocol));
 281   sk->pair = NULL;
 282   release_sock(sk);
 283 }
 284 
 285 
 286 static int
 287 raw_init(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 288 {
 289   struct inet_protocol *p;
 290 
 291   p = (struct inet_protocol *) kmalloc(sizeof (*p), GFP_KERNEL);
 292   if (p == NULL) return(-ENOMEM);
 293 
 294   p->handler = raw_rcv;
 295   p->protocol = sk->protocol;
 296   p->data = (void *)sk;
 297   p->err_handler = raw_err;
 298   inet_add_protocol(p);
 299    
 300   /* We need to remember this somewhere. */
 301   sk->pair = (struct sock *)p;
 302 
 303   DPRINTF((DBG_RAW, "raw init added protocol %d\n", sk->protocol));
 304 
 305   return(0);
 306 }
 307 
 308 
 309 /*
 310  * This should be easy, if there is something there
 311  * we return it, otherwise we block.
 312  */
 313 int
 314 raw_recvfrom(struct sock *sk, unsigned char *to, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 315              int noblock, unsigned flags, struct sockaddr_in *sin,
 316              int *addr_len)
 317 {
 318   int copied=0;
 319   struct sk_buff *skb;
 320 
 321   DPRINTF((DBG_RAW, "raw_recvfrom (sk=%X, to=%X, len=%d, noblock=%d, flags=%X,\n"
 322            "              sin=%X, addr_len=%X)\n",
 323                 sk, to, len, noblock, flags, sin, addr_len));
 324 
 325   if (len == 0) return(0);
 326   if (len < 0) return(-EINVAL);
 327 
 328   if (sk->shutdown & RCV_SHUTDOWN) return(0);
 329   if (addr_len) {
 330         verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
 331         put_fs_long(sizeof(*sin), addr_len);
 332   }
 333   sk->inuse = 1;
 334   while (sk->rqueue == NULL) {
 335         if (noblock) {
 336                 release_sock(sk);
 337                 if (copied) return(copied);
 338                 return(-EAGAIN);
 339         }
 340         release_sock(sk);
 341         cli();
 342         if (sk->rqueue == NULL) {
 343                 interruptible_sleep_on(sk->sleep);
 344                 if (current->signal & ~current->blocked) {
 345                         sti();
 346                         return(-ERESTARTSYS);
 347                 }
 348         }
 349         sk->inuse = 1;
 350         sti();
 351   }
 352   skb = sk->rqueue;
 353 
 354   if (!(flags & MSG_PEEK)) {
 355         if (skb->next == skb) {
 356                 sk->rqueue = NULL;
 357         } else {
 358                 sk->rqueue = (struct sk_buff *)sk->rqueue ->next;
 359                 skb->prev->next = skb->next;
 360                 skb->next->prev = skb->prev;
 361         }
 362   }
 363   copied = min(len, skb->len);
 364   verify_area(VERIFY_WRITE, to, copied);
 365   memcpy_tofs(to, skb->h.raw,  copied);
 366 
 367   /* Copy the address. */
 368   if (sin) {
 369         struct sockaddr_in addr;
 370 
 371         addr.sin_family = AF_INET;
 372         addr.sin_addr.s_addr = skb->daddr;
 373         verify_area(VERIFY_WRITE, sin, sizeof(*sin));
 374         memcpy_tofs(sin, &addr, sizeof(*sin));
 375   }
 376 
 377   if (!(flags & MSG_PEEK)) {
 378         kfree_skb(skb, FREE_READ);
 379   }
 380   release_sock(sk);
 381   return (copied);
 382 }
 383 
 384 
 385 int
 386 raw_read (struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 387           unsigned flags)
 388 {
 389   return(raw_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 390 }
 391 
 392 
 393 struct proto raw_prot = {
 394   sock_wmalloc,
 395   sock_rmalloc,
 396   sock_wfree,
 397   sock_rfree,
 398   sock_rspace,
 399   sock_wspace,
 400   raw_close,
 401   raw_read,
 402   raw_write,
 403   raw_sendto,
 404   raw_recvfrom,
 405   ip_build_header,
 406   udp_connect,
 407   NULL,
 408   ip_queue_xmit,
 409   ip_retransmit,
 410   NULL,
 411   NULL,
 412   raw_rcv,
 413   udp_select,
 414   NULL,
 415   raw_init,
 416   NULL,
 417   128,
 418   0,
 419   {NULL,},
 420   "RAW"
 421 };

/* [previous][next][first][last][top][bottom][index][help] */