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

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