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. 6 * RAW - implementation of IP "raw" sockets. 8 * Version: @(#)raw.c 1.0.4 05/25/93 10 * Authors: Ross Biro, <bir7@leland.Stanford.Edu> 11 * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 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. 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. 40 #include <linux/config.h> 41 #include <asm/system.h> 42 #include <asm/uaccess.h> 43 #include <linux/types.h> 44 #include <linux/sched.h> 45 #include <linux/errno.h> 46 #include <linux/timer.h> 48 #include <linux/kernel.h> 49 #include <linux/fcntl.h> 50 #include <linux/socket.h> 52 #include <linux/inet.h> 53 #include <linux/netdevice.h> 54 #include <linux/mroute.h> 56 #include <net/protocol.h> 57 #include <linux/skbuff.h> 61 #include <net/checksum.h> 63 #ifdef CONFIG_IP_MROUTE 64 struct sock
*mroute_socket
=NULL
; 68 * Raw_err does not currently get called by the icmp module - FIXME: 71 voidraw_err(struct sock
*sk
,struct sk_buff
*skb
) 73 int type
= skb
->h
.icmph
->type
; 74 int code
= skb
->h
.icmph
->code
; 76 if(sk
->ip_recverr
&& !sk
->users
) { 77 struct sk_buff
*skb2
=skb_clone(skb
, GFP_ATOMIC
); 78 if(skb2
&&sock_queue_err_skb(sk
, skb2
)) 79 kfree_skb(skb
, FREE_READ
); 82 if(type
== ICMP_DEST_UNREACH
&& code
== ICMP_FRAG_NEEDED
) { 83 if(sk
->ip_pmtudisc
!= IP_PMTUDISC_DONT
) { 90 static intraw_rcv_skb(struct sock
* sk
,struct sk_buff
* skb
) 92 /* Charge it to the socket. */ 94 if(__sock_queue_rcv_skb(sk
,skb
)<0) 96 ip_statistics
.IpInDiscards
++; 97 kfree_skb(skb
, FREE_READ
); 101 ip_statistics
.IpInDelivers
++; 106 * This should be the easiest of all, all we do is 107 * copy it into a buffer. All demultiplexing is done 111 intraw_rcv(struct sock
*sk
,struct sk_buff
*skb
) 113 /* Now we need to copy this into memory. */ 114 skb_trim(skb
,ntohs(skb
->nh
.iph
->tot_len
)); 116 skb
->h
.raw
= skb
->nh
.raw
; 119 __skb_queue_tail(&sk
->back_log
, skb
); 122 raw_rcv_skb(sk
, skb
); 133 * Send a RAW IP packet. 137 * Callback support is trivial for SOCK_RAW 140 static intraw_getfrag(const void*p
,char*to
,unsigned int offset
,unsigned int fraglen
) 142 struct rawfakehdr
*rfh
= (struct rawfakehdr
*)p
; 143 returncopy_from_user(to
, (const unsigned char*)rfh
->from
+offset
, fraglen
); 147 * IPPROTO_RAW needs extra work. 150 static intraw_getrawfrag(const void*p
,char*to
,unsigned int offset
,unsigned int fraglen
) 152 struct rawfakehdr
*rfh
= (struct rawfakehdr
*)p
; 154 err
=copy_from_user(to
, (const unsigned char*)p
+offset
, fraglen
); 158 struct iphdr
*iph
= (struct iphdr
*)to
; 160 iph
->saddr
= rfh
->saddr
; 162 iph
->tot_len
=htons(fraglen
);/* This is right as you can't frag 165 * Deliberate breach of modularity to keep 166 * ip_build_xmit clean (well less messy). 169 iph
->id
=htons(ip_id_count
++); 170 iph
->check
=ip_fast_csum((unsigned char*)iph
, iph
->ihl
); 175 static intraw_sendto(struct sock
*sk
,const unsigned char*from
, 176 int len
,struct msghdr
*msg
) 178 struct device
*dev
= NULL
; 179 struct ipcm_cookie ipc
; 180 struct rawfakehdr rfh
; 194 if(msg
->msg_flags
& MSG_OOB
)/* Mirror BSD error message compatibility */ 197 if(msg
->msg_flags
& ~(MSG_DONTROUTE
|MSG_DONTWAIT
)) 201 * Get and verify the address. 204 if(msg
->msg_namelen
) { 205 struct sockaddr_in
*usin
= (struct sockaddr_in
*)msg
->msg_name
; 206 if(msg
->msg_namelen
<sizeof(*usin
)) 208 if(usin
->sin_family
!= AF_INET
) { 209 static int complained
; 211 printk("%s forgot to set AF_INET in raw sendmsg. Fix it!\n", current
->comm
); 215 daddr
= usin
->sin_addr
.s_addr
; 216 /* ANK: I did not forget to get protocol from port field. 217 * I just do not know, who uses this weirdness. 218 * IP_HDRINCL is much more convenient. 221 if(sk
->state
!= TCP_ESTABLISHED
) 226 ipc
.addr
= sk
->saddr
; 229 if(msg
->msg_controllen
) { 230 int tmp
=ip_cmsg_send(msg
, &ipc
, &dev
); 233 if(ipc
.opt
&& sk
->ip_hdrincl
) { 241 rfh
.saddr
= ipc
.addr
; 246 if(ipc
.opt
&& ipc
.opt
->srr
) { 249 daddr
= ipc
.opt
->faddr
; 251 tos
=RT_TOS(sk
->ip_tos
) | (sk
->localroute
|| (msg
->msg_flags
&MSG_DONTROUTE
)); 253 if(MULTICAST(daddr
) && sk
->ip_mc_name
[0] && dev
==NULL
) 254 err
=ip_route_output_dev(&rt
, daddr
, rfh
.saddr
, tos
, sk
->ip_mc_name
); 256 err
=ip_route_output(&rt
, daddr
, rfh
.saddr
, tos
, dev
); 259 if(free
)kfree(ipc
.opt
); 263 if(rt
->rt_flags
&RTF_BROADCAST
&& !sk
->broadcast
) { 264 if(free
)kfree(ipc
.opt
); 270 rfh
.saddr
= rt
->rt_src
; 272 ipc
.addr
= rt
->rt_dst
; 274 err
=ip_build_xmit(sk
, raw_getrawfrag
, &rfh
, len
, &ipc
, rt
, msg
->msg_flags
); 276 if(len
>65535-sizeof(struct iphdr
)) 279 err
=ip_build_xmit(sk
, raw_getfrag
, &rfh
, len
, &ipc
, rt
, msg
->msg_flags
); 286 return err
<0? err
: len
; 293 static intraw_sendmsg(struct sock
*sk
,struct msghdr
*msg
,int len
) 295 if(msg
->msg_iovlen
==1) 296 returnraw_sendto(sk
, msg
->msg_iov
[0].iov_base
,len
, msg
); 299 * For awkward cases we linearise the buffer first. In theory this is only frames 300 * whose iovec's don't split on 4 byte boundaries, and soon encrypted stuff (to keep 301 * skip happy). We are a bit more general about it. 308 buf
=kmalloc(len
, GFP_KERNEL
); 311 err
=memcpy_fromiovec(buf
, msg
->msg_iov
, len
); 317 err
=raw_sendto(sk
,buf
,len
, msg
); 328 static voidraw_close(struct sock
*sk
,unsigned long timeout
) 330 sk
->state
= TCP_CLOSE
; 331 #ifdef CONFIG_IP_MROUTE 332 if(sk
==mroute_socket
) 334 ipv4_config
.multicast_route
=0; 344 static intraw_init(struct sock
*sk
) 351 * This should be easy, if there is something there 352 * we return it, otherwise we block. 355 intraw_recvmsg(struct sock
*sk
,struct msghdr
*msg
,int len
, 356 int noblock
,int flags
,int*addr_len
) 361 struct sockaddr_in
*sin
=(struct sockaddr_in
*)msg
->msg_name
; 366 if(sk
->shutdown
& RCV_SHUTDOWN
) 370 *addr_len
=sizeof(*sin
); 372 if(sk
->ip_recverr
&& (skb
=skb_dequeue(&sk
->error_queue
)) != NULL
) { 374 if(msg
->msg_controllen
==0) { 375 skb_free_datagram(sk
, skb
); 378 put_cmsg(msg
, SOL_IP
, IP_RECVERR
, skb
->len
, skb
->data
); 379 skb_free_datagram(sk
, skb
); 383 skb
=skb_recv_datagram(sk
,flags
,noblock
,&err
); 390 msg
->msg_flags
|= MSG_TRUNC
; 394 err
=skb_copy_datagram_iovec(skb
,0, msg
->msg_iov
, copied
); 395 sk
->stamp
=skb
->stamp
; 397 /* Copy the address. */ 399 sin
->sin_family
= AF_INET
; 400 sin
->sin_addr
.s_addr
= skb
->nh
.iph
->saddr
; 402 if(sk
->ip_cmsg_flags
) 403 ip_cmsg_recv(msg
, skb
); 404 skb_free_datagram(sk
, skb
); 405 return err
? err
: (copied
); 409 struct proto raw_prot
= { 417 #ifdef CONFIG_IP_MROUTE 429 NULL
,/* No special bind */