linux/net/ipv4/datagram.c
<<
>>
Prefs
   1/*
   2 *      common UDP/RAW code
   3 *      Linux INET implementation
   4 *
   5 * Authors:
   6 *      Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
   7 *
   8 *      This program is free software; you can redistribute it and/or
   9 *      modify it under the terms of the GNU General Public License
  10 *      as published by the Free Software Foundation; either version
  11 *      2 of the License, or (at your option) any later version.
  12 */
  13
  14#include <linux/types.h>
  15#include <linux/module.h>
  16#include <linux/ip.h>
  17#include <linux/in.h>
  18#include <net/ip.h>
  19#include <net/sock.h>
  20#include <net/route.h>
  21#include <net/tcp_states.h>
  22
  23int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
  24{
  25        struct inet_sock *inet = inet_sk(sk);
  26        struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
  27        struct rtable *rt;
  28        __be32 saddr;
  29        int oif;
  30        int err;
  31
  32
  33        if (addr_len < sizeof(*usin))
  34                return -EINVAL;
  35
  36        if (usin->sin_family != AF_INET)
  37                return -EAFNOSUPPORT;
  38
  39        sk_dst_reset(sk);
  40
  41        oif = sk->sk_bound_dev_if;
  42        saddr = inet->saddr;
  43        if (ipv4_is_multicast(usin->sin_addr.s_addr)) {
  44                if (!oif)
  45                        oif = inet->mc_index;
  46                if (!saddr)
  47                        saddr = inet->mc_addr;
  48        }
  49        err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
  50                               RT_CONN_FLAGS(sk), oif,
  51                               sk->sk_protocol,
  52                               inet->sport, usin->sin_port, sk, 1);
  53        if (err) {
  54                if (err == -ENETUNREACH)
  55                        IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
  56                return err;
  57        }
  58
  59        if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
  60                ip_rt_put(rt);
  61                return -EACCES;
  62        }
  63        if (!inet->saddr)
  64                inet->saddr = rt->rt_src;       /* Update source address */
  65        if (!inet->rcv_saddr)
  66                inet->rcv_saddr = rt->rt_src;
  67        inet->daddr = rt->rt_dst;
  68        inet->dport = usin->sin_port;
  69        sk->sk_state = TCP_ESTABLISHED;
  70        inet->id = jiffies;
  71
  72        sk_dst_set(sk, &rt->u.dst);
  73        return(0);
  74}
  75
  76EXPORT_SYMBOL(ip4_datagram_connect);
  77
  78