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

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