Auteur Sujet: TCP/UDP : Le port 0 existe-t-il ?  (Lu 30047 fois)

0 Membres et 1 Invité sur ce sujet

corrector

  • Invité
TCP/UDP : Le port 0 existe-t-il ?
« Réponse #60 le: 27 mars 2016 à 11:04:42 »
Pour connect sur socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) :

994 static struct inet_protosw inetsw_array[] =
995 {
996         {
997                 .type =       SOCK_STREAM,
998                 .protocol =   IPPROTO_TCP,
999                 .prot =       &tcp_prot,
1000                 .ops =        &inet_stream_ops,
1003         },

http://lxr.free-electrons.com/source/net/ipv4/af_inet.c#L994

900 const struct proto_ops inet_stream_ops = {
901         .family            = PF_INET,
...
905         .connect           = inet_stream_connect,

http://lxr.free-electrons.com/source/net/ipv4/af_inet.c#L900

651 int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
652                         int addr_len, int flags)
653 {
...
657         err = __inet_stream_connect(sock, uaddr, addr_len, flags);

http://lxr.free-electrons.com/source/net/ipv4/af_inet.c#L651

560 /*
561  *      Connect to a remote host. There is regrettably still a little
562  *      TCP 'magic' in here.
563  */
564 int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr,
565                           int addr_len, int flags)
566 {
...
580         switch (sock->state) {
....
591         case SS_UNCONNECTED:
...
596                 err = sk->sk_prot->connect(sk, uaddr, addr_len);

http://lxr.free-electrons.com/source/net/ipv4/af_inet.c#L560

2315 struct proto tcp_prot = {
2316         .name                   = "TCP",
...
2319         .connect                = tcp_v4_connect,

http://lxr.free-electrons.com/source/net/ipv4/tcp_ipv4.c#L2315

139 /* This will initiate an outgoing connection. */
140 int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
141 {
142         struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
143         struct inet_sock *inet = inet_sk(sk);
144         struct tcp_sock *tp = tcp_sk(sk);
145         __be16 orig_sport, orig_dport;
146         __be32 daddr, nexthop;
147         struct flowi4 *fl4;
148         struct rtable *rt;
...
167         orig_sport = inet->inet_sport;
168         orig_dport = usin->sin_port;
169         fl4 = &inet->cork.fl.u.ip4;
170         rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
171                               RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
172                               IPPROTO_TCP,
173                               orig_sport, orig_dport, sk);
...
226         rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
227                                inet->inet_sport, inet->inet_dport, sk);
...
245         err = tcp_connect(sk);

http://lxr.free-electrons.com/source/net/ipv4/tcp_ipv4.c#L139

273 static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
274                                               __be32 dst, __be32 src, u32 tos,
275                                               int oif, u8 protocol,
276                                               __be16 sport, __be16 dport,
277                                               struct sock *sk)
278 {
279         struct net *net = sock_net(sk);
280         struct rtable *rt;
281
282         ip_route_connect_init(fl4, dst, src, tos, oif, protocol,
283                               sport, dport, sk);
284
285         if (!src && oif) {
286                 int rc;
287
288                 rc = l3mdev_get_saddr(net, oif, fl4);
289                 if (rc < 0)
290                         return ERR_PTR(rc);
291
292                 src = fl4->saddr;
293         }
294         if (!dst || !src) {
295                 rt = __ip_route_output_key(net, fl4);
296                 if (IS_ERR(rt))
297                         return rt;
298                 ip_rt_put(rt);
299                 flowi4_update_output(fl4, oif, tos, fl4->daddr, fl4->saddr);
300         }
301         security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
302         return ip_route_output_flow(net, fl4, sk);
303 }
304
305 static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable *rt,
306                                                __be16 orig_sport, __be16 orig_dport,
307                                                __be16 sport, __be16 dport,
308                                                struct sock *sk)
309 {
310         if (sport != orig_sport || dport != orig_dport) {
311                 fl4->fl4_dport = dport;
312                 fl4->fl4_sport = sport;
313                 ip_rt_put(rt);
314                 flowi4_update_output(fl4, sk->sk_bound_dev_if,
315                                      RT_CONN_FLAGS(sk), fl4->daddr,
316                                      fl4->saddr);
317                 security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
318                 return ip_route_output_flow(sock_net(sk), fl4, sk);
319         }
320         return rt;
321 }

http://lxr.free-electrons.com/source/include/net/route.h#L273

Je ne vois rien ici qui contraigne la valeur du port destination.

corrector

  • Invité
TCP/UDP : Le port 0 existe-t-il ?
« Réponse #61 le: 27 mars 2016 à 12:26:17 »
Dans Linux, le port n'est pas utilisable par bind() :
Si, il l'est :
422 int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
423 {
424         struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
425         struct sock *sk = sock->sk;
426         struct inet_sock *inet = inet_sk(sk);
427         struct net *net = sock_net(sk);
428         unsigned short snum;
429         int chk_addr_ret;
430         u32 tb_id = RT_TABLE_LOCAL;
431         int err;
432
433         /* If the socket has its own bind function then use it. (RAW) */
434         if (sk->sk_prot->bind) {
435                 err = sk->sk_prot->bind(sk, uaddr, addr_len);
436                 goto out;
437         }
...
495         /* Make sure we are allowed to bind here. */
496         if ((snum || !inet->bind_address_no_port) &&
497             sk->sk_prot->get_port(sk, snum))

http://lxr.free-electrons.com/source/net/ipv4/af_inet.c#L422

static int do_ip_setsockopt(struct sock *sk, int level,
             int optname, char __user *optval, unsigned int optlen)
{
...
   case IP_BIND_ADDRESS_NO_PORT:
      inet->bind_address_no_port = val ? 1 : 0;
      break;

http://lxr.free-electrons.com/source/net/ipv4/ip_sockglue.c

Donc oui tu peux appeler bind avec un port 0 avec la bonne option, mais non, ça ne sert à rien, comme j'ai montré avec listen.

corrector

  • Invité
TCP/UDP : Le port 0 existe-t-il ?
« Réponse #62 le: 27 mars 2016 à 13:03:49 »
J'ai oublié ça :

139 /* This will initiate an outgoing connection. */
140 int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
141 {
...
220         err = inet_hash_connect(&tcp_death_row, sk);

http://lxr.free-electrons.com/source/net/ipv4/tcp_ipv4.c#L139

611 /*
612  * Bind a port for a connect operation and hash it.
613  */
614 int inet_hash_connect(struct inet_timewait_death_row *death_row,
615                       struct sock *sk)
616 {
617         u32 port_offset = 0;
618
619         if (!inet_sk(sk)->inet_num)
620                 port_offset = inet_sk_port_offset(sk);
621         return __inet_hash_connect(death_row, sk, port_offset,
622                                    __inet_check_established);
623 }

http://lxr.free-electrons.com/source/net/ipv4/inet_hashtables.c#L611

503 int __inet_hash_connect(struct inet_timewait_death_row *death_row,
504                 struct sock *sk, u32 port_offset,
505                 int (*check_established)(struct inet_timewait_death_row *,
506                         struct sock *, __u16, struct inet_timewait_sock **))
507 {
...
515         if (!snum) {

http://lxr.free-electrons.com/source/net/ipv4/inet_hashtables.c#L503