2005-04-17 02:20:36 +04:00
/*
* common UDP / RAW code
* Linux INET implementation
*
* Authors :
* Hideaki YOSHIFUJI < yoshfuji @ linux - ipv6 . org >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version
* 2 of the License , or ( at your option ) any later version .
*/
# include <linux/types.h>
# include <linux/module.h>
# include <linux/ip.h>
# include <linux/in.h>
2005-08-16 09:18:02 +04:00
# include <net/ip.h>
2005-04-17 02:20:36 +04:00
# include <net/sock.h>
# include <net/route.h>
2005-08-10 07:08:28 +04:00
# include <net/tcp_states.h>
2005-04-17 02:20:36 +04:00
int ip4_datagram_connect ( struct sock * sk , struct sockaddr * uaddr , int addr_len )
{
struct inet_sock * inet = inet_sk ( sk ) ;
struct sockaddr_in * usin = ( struct sockaddr_in * ) uaddr ;
struct rtable * rt ;
u32 saddr ;
int oif ;
int err ;
if ( addr_len < sizeof ( * usin ) )
return - EINVAL ;
if ( usin - > sin_family ! = AF_INET )
return - EAFNOSUPPORT ;
sk_dst_reset ( sk ) ;
oif = sk - > sk_bound_dev_if ;
saddr = inet - > saddr ;
if ( MULTICAST ( usin - > sin_addr . s_addr ) ) {
if ( ! oif )
oif = inet - > mc_index ;
if ( ! saddr )
saddr = inet - > mc_addr ;
}
err = ip_route_connect ( & rt , usin - > sin_addr . s_addr , saddr ,
RT_CONN_FLAGS ( sk ) , oif ,
sk - > sk_protocol ,
inet - > sport , usin - > sin_port , sk ) ;
if ( err )
return err ;
if ( ( rt - > rt_flags & RTCF_BROADCAST ) & & ! sock_flag ( sk , SOCK_BROADCAST ) ) {
ip_rt_put ( rt ) ;
return - EACCES ;
}
if ( ! inet - > saddr )
inet - > saddr = rt - > rt_src ; /* Update source address */
if ( ! inet - > rcv_saddr )
inet - > rcv_saddr = rt - > rt_src ;
inet - > daddr = rt - > rt_dst ;
inet - > dport = usin - > sin_port ;
sk - > sk_state = TCP_ESTABLISHED ;
inet - > id = jiffies ;
sk_dst_set ( sk , & rt - > u . dst ) ;
return ( 0 ) ;
}
EXPORT_SYMBOL ( ip4_datagram_connect ) ;