root/net/ipv4/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_skb
  4. raw_rcv_redo
  5. raw_rcv
  6. raw_getfrag
  7. raw_getrawfrag
  8. raw_sendto
  9. raw_sendmsg
  10. raw_close
  11. raw_init
  12. raw_recvmsg

   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  *              Alan Cox        :       Use new kernel side addresses
  28  *      Arnt Gulbrandsen        :       Fixed MSG_DONTROUTE in raw sockets.
  29  *              Alan Cox        :       BSD style RAW socket demultiplexing.
  30  *              Alan Cox        :       Beginnings of mrouted support.
  31  *              Alan Cox        :       Added IP_HDRINCL option.
  32  *              Alan Cox        :       Skip broadcast check if BSDism set.
  33  *
  34  *              This program is free software; you can redistribute it and/or
  35  *              modify it under the terms of the GNU General Public License
  36  *              as published by the Free Software Foundation; either version
  37  *              2 of the License, or (at your option) any later version.
  38  */
  39  
  40 #include <linux/config.h> 
  41 #include <asm/system.h>
  42 #include <asm/segment.h>
  43 #include <linux/types.h>
  44 #include <linux/sched.h>
  45 #include <linux/errno.h>
  46 #include <linux/timer.h>
  47 #include <linux/mm.h>
  48 #include <linux/kernel.h>
  49 #include <linux/fcntl.h>
  50 #include <linux/socket.h>
  51 #include <linux/in.h>
  52 #include <linux/inet.h>
  53 #include <linux/netdevice.h>
  54 #include <linux/mroute.h>
  55 #include <net/ip.h>
  56 #include <net/protocol.h>
  57 #include <linux/skbuff.h>
  58 #include <net/sock.h>
  59 #include <net/icmp.h>
  60 #include <net/udp.h>
  61 #include <net/checksum.h>
  62 
  63 #ifdef CONFIG_IP_MROUTE
  64 struct sock *mroute_socket=NULL;
  65 #endif
  66 
  67 static inline unsigned long min(unsigned long a, unsigned long b)
     /* [previous][next][first][last][top][bottom][index][help] */
  68 {
  69         if (a < b) 
  70                 return(a);
  71         return(b);
  72 }
  73 
  74 
  75 /*
  76  *      Raw_err does not currently get called by the icmp module - FIXME:
  77  */
  78  
  79 void raw_err (int type, int code, unsigned char *header, __u32 daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
  80          __u32 saddr, struct inet_protocol *protocol)
  81 {
  82         struct sock *sk;
  83    
  84         if (protocol == NULL) 
  85                 return;
  86         sk = (struct sock *) protocol->data;
  87         if (sk == NULL) 
  88                 return;
  89 
  90         /* This is meaningless in raw sockets. */
  91         if (type == ICMP_SOURCE_QUENCH) 
  92         {
  93                 if (sk->cong_window > 1) sk->cong_window = sk->cong_window/2;
  94                 return;
  95         }
  96         
  97         if(type == ICMP_PARAMETERPROB)
  98         {
  99                 sk->err = EPROTO;
 100                 sk->error_report(sk);
 101         }
 102 
 103         if(code<13)
 104         {
 105                 sk->err = icmp_err_convert[code & 0xff].errno;
 106                 sk->error_report(sk);
 107         }
 108         
 109         return;
 110 }
 111 
 112 static inline void raw_rcv_skb(struct sock * sk, struct sk_buff * skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114         /* Charge it to the socket. */
 115         
 116         if (sock_queue_rcv_skb(sk,skb)<0)
 117         {
 118                 ip_statistics.IpInDiscards++;
 119                 skb->sk=NULL;
 120                 kfree_skb(skb, FREE_READ);
 121                 return;
 122         }
 123 
 124         ip_statistics.IpInDelivers++;
 125 }
 126 
 127 /*
 128  * This is the prot->rcv() function. It's called when we have
 129  * backlogged packets from core/sock.c if we couldn't receive it
 130  * when the packet arrived.
 131  */
 132 static int raw_rcv_redo(struct sk_buff *skb, struct device *dev, struct options *opt,
     /* [previous][next][first][last][top][bottom][index][help] */
 133         __u32 daddr, unsigned short len,
 134         __u32 saddr, int redo, struct inet_protocol * protocol)
 135 {
 136         raw_rcv_skb(skb->sk, skb);
 137         return 0;
 138 }
 139 
 140 /*
 141  *      This should be the easiest of all, all we do is
 142  *      copy it into a buffer. All demultiplexing is done
 143  *      in ip.c
 144  */
 145 
 146 int raw_rcv(struct sock *sk, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 147 {
 148         /* Now we need to copy this into memory. */
 149         skb->sk = sk;
 150         skb_trim(skb,ntohs(skb->ip_hdr->tot_len));
 151         
 152         skb->h.raw = (unsigned char *) skb->ip_hdr;
 153         skb->dev = dev;
 154         skb->saddr = daddr;
 155         skb->daddr = saddr;
 156 
 157 #if 0   
 158         /*
 159          *      For no adequately explained reasons BSD likes to mess up the header of
 160          *      the received frame. 
 161          */
 162          
 163         if(sk->bsdism)
 164                 skb->ip_hdr->tot_len=ntohs(skb->ip_hdr->tot_len-4*skb->ip_hdr->ihl);
 165 #endif
 166         
 167         if (sk->users) {
 168                 __skb_queue_tail(&sk->back_log, skb);
 169                 return 0;
 170         }
 171         raw_rcv_skb(sk, skb);
 172         return 0;
 173 }
 174 
 175 /*
 176  *      Send a RAW IP packet.
 177  */
 178 
 179 /*
 180  *      Callback support is trivial for SOCK_RAW
 181  */
 182   
 183 static void raw_getfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
     /* [previous][next][first][last][top][bottom][index][help] */
 184 {
 185         memcpy_fromfs(to, (const unsigned char *)p+offset, fraglen);
 186 }
 187 
 188 /*
 189  *      IPPROTO_RAW needs extra work.
 190  */
 191  
 192 static void raw_getrawfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
     /* [previous][next][first][last][top][bottom][index][help] */
 193 {
 194         memcpy_fromfs(to, (const unsigned char *)p+offset, fraglen);
 195         if(offset==0)
 196         {
 197                 struct iphdr *iph=(struct iphdr *)to;
 198                 if(!iph->saddr)
 199                         iph->saddr=saddr;
 200                 iph->check=0;
 201                 iph->tot_len=htons(fraglen);    /* This is right as you cant frag
 202                                            RAW packets */
 203                 /*
 204                  *      Deliberate breach of modularity to keep 
 205                  *      ip_build_xmit clean (well less messy).
 206                  */
 207                 iph->id = htons(ip_id_count++);
 208                 iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl);
 209         }
 210 }
 211 
 212 static int raw_sendto(struct sock *sk, const unsigned char *from, 
     /* [previous][next][first][last][top][bottom][index][help] */
 213         int len, int noblock, unsigned flags, struct sockaddr_in *usin, int addr_len)
 214 {
 215         int err;
 216         struct sockaddr_in sin;
 217 
 218         /*
 219          *      Check the flags. Only MSG_DONTROUTE is permitted.
 220          */
 221 
 222         if (flags & MSG_OOB)            /* Mirror BSD error message compatibility */
 223                 return -EOPNOTSUPP;
 224                          
 225         if (flags & ~MSG_DONTROUTE)
 226                 return(-EINVAL);
 227         /*
 228          *      Get and verify the address. 
 229          */
 230 
 231         if (usin) 
 232         {
 233                 if (addr_len < sizeof(sin)) 
 234                         return(-EINVAL);
 235                 memcpy(&sin, usin, sizeof(sin));
 236                 if (sin.sin_family && sin.sin_family != AF_INET) 
 237                         return(-EINVAL);
 238         }
 239         else 
 240         {
 241                 if (sk->state != TCP_ESTABLISHED) 
 242                         return(-EINVAL);
 243                 sin.sin_family = AF_INET;
 244                 sin.sin_port = sk->num;
 245                 sin.sin_addr.s_addr = sk->daddr;
 246         }
 247         if (sin.sin_port == 0) 
 248                 sin.sin_port = sk->num;
 249   
 250         if (sin.sin_addr.s_addr == INADDR_ANY)
 251                 sin.sin_addr.s_addr = ip_my_addr();
 252 
 253         /*
 254          *      BSD raw sockets forget to check SO_BROADCAST ....
 255          */
 256          
 257         if (!sk->bsdism && sk->broadcast == 0 && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
 258                 return -EACCES;
 259 
 260         if(sk->ip_hdrincl)
 261         {
 262                 if(len>65535)
 263                         return -EMSGSIZE;
 264                 err=ip_build_xmit(sk, raw_getrawfrag, from, len, sin.sin_addr.s_addr, 0, sk->opt, flags, sin.sin_port, noblock);
 265         }
 266         else
 267         {
 268                 if(len>65535-sizeof(struct iphdr))
 269                         return -EMSGSIZE;
 270                 err=ip_build_xmit(sk, raw_getfrag, from, len, sin.sin_addr.s_addr, 0, sk->opt, flags, sin.sin_port, noblock);
 271         }
 272         return err<0?err:len;
 273 }
 274 
 275 /*
 276  *      Temporary
 277  */
 278  
 279 static int raw_sendmsg(struct sock *sk, struct msghdr *msg, int len, int noblock, 
     /* [previous][next][first][last][top][bottom][index][help] */
 280         int flags)
 281 {
 282         if(msg->msg_iovlen==1)
 283                 return raw_sendto(sk,msg->msg_iov[0].iov_base,len, noblock, flags, msg->msg_name, msg->msg_namelen);
 284         else
 285         {
 286                 /*
 287                  *      For awkward cases we linearise the buffer first. In theory this is only frames
 288                  *      whose iovec's don't split on 4 byte boundaries, and soon encrypted stuff (to keep
 289                  *      skip happy). We are a bit more general about it.
 290                  */
 291                  
 292                 unsigned char *buf;
 293                 int fs;
 294                 int err;
 295                 if(len>65515)
 296                         return -EMSGSIZE;
 297                 buf=kmalloc(len, GFP_KERNEL);
 298                 if(buf==NULL)
 299                         return -ENOBUFS;
 300                 memcpy_fromiovec(buf, msg->msg_iov, len);
 301                 fs=get_fs();
 302                 set_fs(get_ds());
 303                 err=raw_sendto(sk,buf,len, noblock, flags, msg->msg_name, msg->msg_namelen);
 304                 set_fs(fs);
 305                 kfree_s(buf,len);
 306                 return err;
 307         }
 308 }
 309 
 310 static void raw_close(struct sock *sk, unsigned long timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 311 {
 312         sk->state = TCP_CLOSE;
 313 #ifdef CONFIG_IP_MROUTE 
 314         if(sk==mroute_socket)
 315         {
 316                 mroute_close(sk);
 317                 mroute_socket=NULL;
 318         }
 319 #endif  
 320         destroy_sock(sk);
 321 }
 322 
 323 
 324 static int raw_init(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 325 {
 326         return(0);
 327 }
 328 
 329 
 330 /*
 331  *      This should be easy, if there is something there
 332  *      we return it, otherwise we block.
 333  */
 334 
 335 int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 336      int noblock, int flags,int *addr_len)
 337 {
 338         int copied=0;
 339         struct sk_buff *skb;
 340         int err;
 341         struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
 342 
 343         if (flags & MSG_OOB)
 344                 return -EOPNOTSUPP;
 345                 
 346         if (sk->shutdown & RCV_SHUTDOWN) 
 347                 return(0);
 348 
 349         if (addr_len) 
 350                 *addr_len=sizeof(*sin);
 351 
 352         skb=skb_recv_datagram(sk,flags,noblock,&err);
 353         if(skb==NULL)
 354                 return err;
 355 
 356         copied = min(len, skb->len);
 357         
 358         skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 359         sk->stamp=skb->stamp;
 360 
 361         /* Copy the address. */
 362         if (sin) 
 363         {
 364                 sin->sin_family = AF_INET;
 365                 sin->sin_addr.s_addr = skb->daddr;
 366         }
 367         skb_free_datagram(sk, skb);
 368         return (copied);
 369 }
 370 
 371 
 372 struct proto raw_prot = {
 373         raw_close,
 374         ip_build_header,
 375         udp_connect,
 376         NULL,
 377         ip_queue_xmit,
 378         NULL,
 379         NULL,
 380         NULL,
 381         raw_rcv_redo,
 382         datagram_select,
 383 #ifdef CONFIG_IP_MROUTE 
 384         ipmr_ioctl,
 385 #else
 386         NULL,
 387 #endif          
 388         raw_init,
 389         NULL,
 390         ip_setsockopt,
 391         ip_getsockopt,
 392         raw_sendmsg,
 393         raw_recvmsg,
 394         NULL,           /* No special bind */
 395         128,
 396         0,
 397         "RAW",
 398         0, 0,
 399         {NULL,}
 400 };

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