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 "timer.h"
  31 #include "dev.h"
  32 #include "ip.h"
  33 #include "protocol.h"
  34 #include "tcp.h"
  35 #include "skbuff.h"
  36 #include "sock.h"
  37 #include "icmp.h"
  38 #include "udp.h"
  39 
  40 
  41 static unsigned long
  42 min(unsigned long a, unsigned long b)
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44   if (a < b) return(a);
  45   return(b);
  46 }
  47 
  48 
  49 /* raw_err gets called by the icmp module. */
  50 void
  51 raw_err (int err, unsigned char *header, unsigned long daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
  52          unsigned long saddr, struct inet_protocol *protocol)
  53 {
  54   struct sock *sk;
  55    
  56   DPRINTF((DBG_RAW, "raw_err(err=%d, hdr=%X, daddr=%X, saddr=%X, protocl=%X)\n",
  57                 err, header, daddr, saddr, protocol));
  58 
  59   if (protocol == NULL) return;
  60   sk = protocol->data;
  61   if (sk == NULL) return;
  62 
  63   /* This is meaningless in raw sockets. */
  64   if (err & 0xff00 == (ICMP_SOURCE_QUENCH << 8)) {
  65         if (sk->cong_window > 1) sk->cong_window = sk->cong_window/2;
  66         return;
  67   }
  68 
  69   sk->err = icmp_err_convert[err & 0xff].errno;
  70 
  71   /* None of them are fatal for raw sockets. */
  72 #if 0
  73   if (icmp_err_convert[err & 0xff].fatal) {
  74         sk->prot->close(sk, 0);
  75   }
  76 #endif
  77   return;
  78 }
  79 
  80 
  81 /*
  82  * This should be the easiest of all, all we do is\
  83  * copy it into a buffer.
  84  */
  85 int
  86 raw_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
  87         unsigned long daddr, unsigned short len, unsigned long saddr,
  88         int redo, struct inet_protocol *protocol)
  89 {
  90   struct sock *sk;
  91 
  92   DPRINTF((DBG_RAW, "raw_rcv(skb=%X, dev=%X, opt=%X, daddr=%X,\n"
  93            "         len=%d, saddr=%X, redo=%d, protocol=%X)\n",
  94            skb, dev, opt, daddr, len, saddr, redo, protocol));
  95 
  96   if (skb == NULL) return(0);
  97   if (protocol == NULL) {
  98         kfree_skb(skb, FREE_READ);
  99         return(0);
 100   }
 101   sk = protocol->data;
 102   if (sk == NULL) {
 103         kfree_skb(skb, FREE_READ);
 104         return(0);
 105   }
 106 
 107   /* Now we need to copy this into memory. */
 108   skb->sk = sk;
 109   skb->len = len;
 110   skb->dev = dev;
 111   skb->saddr = daddr;
 112   skb->daddr = saddr;
 113 
 114   if (!redo) {
 115         /* Now see if we are in use. */
 116         cli();
 117         if (sk->inuse) {
 118                 DPRINTF((DBG_RAW, "raw_rcv adding to backlog.\n"));
 119                 if (sk->back_log == NULL) {
 120                         sk->back_log = skb;
 121                         skb->next = skb;
 122                         skb->prev = skb;
 123                 } else {
 124                         skb->next = sk->back_log;
 125                         skb->prev = sk->back_log->prev;
 126                         skb->prev->next = skb;
 127                         skb->next->prev = skb;
 128                 }
 129                 sti();
 130                 return(0);
 131         }
 132         sk->inuse = 1;
 133         sti();
 134   }
 135 
 136   /* Charge it too the socket. */
 137   if (sk->rmem_alloc + skb->mem_len >= SK_RMEM_MAX) {
 138         skb->sk = NULL;
 139         kfree_skb(skb, FREE_READ);
 140         return(0);
 141   }
 142   sk->rmem_alloc += skb->mem_len;
 143 
 144   /* Now just put it onto the queue. */
 145   if (sk->rqueue == NULL) {
 146         sk->rqueue = skb;
 147         skb->next = skb;
 148         skb->prev = skb;
 149   } else {
 150         skb->next = sk->rqueue;
 151         skb->prev = sk->rqueue->prev;
 152         skb->prev->next = skb;
 153         skb->next->prev = skb;
 154   }
 155   wake_up(sk->sleep);
 156   release_sock(sk);
 157   return(0);
 158 }
 159 
 160 
 161 /* This will do terrible things if len + ipheader + devheader > dev->mtu */
 162 static int
 163 raw_sendto(struct sock *sk, unsigned char *from, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 164            int noblock,
 165            unsigned flags, struct sockaddr_in *usin, int addr_len)
 166 {
 167   struct sk_buff *skb;
 168   struct device *dev=NULL;
 169   struct sockaddr_in sin;
 170   int tmp;
 171 
 172   DPRINTF((DBG_RAW, "raw_sendto(sk=%X, from=%X, len=%d, noblock=%d, flags=%X,\n"
 173            "            usin=%X, addr_len = %d)\n", sk, from, len, noblock,
 174            flags, usin, addr_len));
 175 
 176   /* Check the flags. */
 177   if (flags) return(-EINVAL);
 178   if (len < 0) return(-EINVAL);
 179 
 180   /* Get and verify the address. */
 181   if (usin) {
 182         if (addr_len < sizeof(sin)) return(-EINVAL);
 183         /* verify_area (VERIFY_WRITE, usin, sizeof (sin));*/
 184         memcpy_fromfs(&sin, usin, sizeof(sin));
 185         if (sin.sin_family && sin.sin_family != AF_INET) return(-EINVAL);
 186   } else {
 187         if (sk->state != TCP_ESTABLISHED) return(-EINVAL);
 188         sin.sin_family = AF_INET;
 189         sin.sin_port = sk->protocol;
 190         sin.sin_addr.s_addr = sk->daddr;
 191   }
 192   if (sin.sin_port == 0) sin.sin_port = sk->protocol;
 193 
 194   sk->inuse = 1;
 195   skb = NULL;
 196   while (skb == NULL) {
 197         skb = sk->prot->wmalloc(sk, 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   skb->len = tmp + len;
 241   sk->prot->queue_xmit(sk, dev, skb, 1);
 242   release_sock(sk);
 243   return(len);
 244 }
 245 
 246 
 247 static int
 248 raw_write(struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 249            unsigned flags)
 250 {
 251   return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0));
 252 }
 253 
 254 
 255 static void
 256 raw_close(struct sock *sk, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 257 {
 258   sk->inuse = 1;
 259   sk->state = TCP_CLOSE;
 260 
 261   DPRINTF((DBG_RAW, "raw_close: deleting protocol %d\n",
 262            ((struct inet_protocol *)sk->pair)->protocol));
 263 
 264   if (inet_del_protocol((struct inet_protocol *)sk->pair) < 0)
 265                 DPRINTF((DBG_RAW, "raw_close: del_protocol failed.\n"));
 266   kfree_s((void *)sk->pair, sizeof (struct inet_protocol));
 267   sk->pair = NULL;
 268   release_sock(sk);
 269 }
 270 
 271 
 272 static int
 273 raw_init(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 274 {
 275   struct inet_protocol *p;
 276 
 277   p = kmalloc(sizeof (*p), GFP_KERNEL);
 278   if (p == NULL) return(-ENOMEM);
 279 
 280   p->handler = raw_rcv;
 281   p->protocol = sk->protocol;
 282   p->data = (void *)sk;
 283   p->err_handler = raw_err;
 284   inet_add_protocol(p);
 285    
 286   /* We need to remember this somewhere. */
 287   sk->pair = (struct sock *)p;
 288 
 289   DPRINTF((DBG_RAW, "raw init added protocol %d\n", sk->protocol));
 290 
 291   return(0);
 292 }
 293 
 294 
 295 /*
 296  * This should be easy, if there is something there
 297  * we return it, otherwise we block.
 298  */
 299 int
 300 raw_recvfrom(struct sock *sk, unsigned char *to, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 301              int noblock, unsigned flags, struct sockaddr_in *sin,
 302              int *addr_len)
 303 {
 304   int copied=0;
 305   struct sk_buff *skb;
 306 
 307   DPRINTF((DBG_RAW, "raw_recvfrom (sk=%X, to=%X, len=%d, noblock=%d, flags=%X,\n"
 308            "              sin=%X, addr_len=%X)\n",
 309                 sk, to, len, noblock, flags, sin, addr_len));
 310 
 311   if (len == 0) return(0);
 312   if (len < 0) return(-EINVAL);
 313 
 314   if (sk->shutdown & RCV_SHUTDOWN) return(0);
 315   if (addr_len) {
 316         verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
 317         put_fs_long(sizeof(*sin), addr_len);
 318   }
 319   sk->inuse = 1;
 320   while (sk->rqueue == NULL) {
 321         if (noblock) {
 322                 release_sock(sk);
 323                 if (copied) return(copied);
 324                 return(-EAGAIN);
 325         }
 326         release_sock(sk);
 327         cli();
 328         if (sk->rqueue == NULL) {
 329                 interruptible_sleep_on(sk->sleep);
 330                 if (current->signal & ~current->blocked) {
 331                         sti();
 332                         return(-ERESTARTSYS);
 333                 }
 334         }
 335         sk->inuse = 1;
 336         sti();
 337   }
 338   skb = sk->rqueue;
 339 
 340   if (!(flags & MSG_PEEK)) {
 341         if (skb->next == skb) {
 342                 sk->rqueue = NULL;
 343         } else {
 344                 sk->rqueue = (struct sk_buff *)sk->rqueue ->next;
 345                 skb->prev->next = skb->next;
 346                 skb->next->prev = skb->prev;
 347         }
 348   }
 349   copied = min(len, skb->len);
 350   verify_area(VERIFY_WRITE, to, copied);
 351   memcpy_tofs(to, skb->h.raw,  copied);
 352 
 353   /* Copy the address. */
 354   if (sin) {
 355         struct sockaddr_in addr;
 356 
 357         addr.sin_family = AF_INET;
 358         addr.sin_addr.s_addr = skb->daddr;
 359         verify_area(VERIFY_WRITE, sin, sizeof(*sin));
 360         memcpy_tofs(sin, &addr, sizeof(*sin));
 361   }
 362 
 363   if (!(flags & MSG_PEEK)) {
 364         kfree_skb(skb, FREE_READ);
 365   }
 366   release_sock(sk);
 367   return (copied);
 368 }
 369 
 370 
 371 int
 372 raw_read (struct sock *sk, unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 373           unsigned flags)
 374 {
 375   return(raw_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 376 }
 377 
 378 
 379 struct proto raw_prot = {
 380   sock_wmalloc,
 381   sock_rmalloc,
 382   sock_wfree,
 383   sock_rfree,
 384   sock_rspace,
 385   sock_wspace,
 386   raw_close,
 387   raw_read,
 388   raw_write,
 389   raw_sendto,
 390   raw_recvfrom,
 391   ip_build_header,
 392   udp_connect,
 393   NULL,
 394   ip_queue_xmit,
 395   ip_retransmit,
 396   NULL,
 397   NULL,
 398   raw_rcv,
 399   udp_select,
 400   NULL,
 401   raw_init,
 402   NULL,
 403   128,
 404   0,
 405   {NULL,},
 406   "RAW"
 407 };

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