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

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