On Sun, Apr 03, 2016 at 10:17:49PM +0200, Vincent Gross wrote:
> in_pcbpickport() need the local address, so I extend the prototype and
> keep a void * to the sin(6)_addr or zeroin46_addr. And while at it, I set
> the INPLOOKUP_IPV6 flag which will be needed in in_pcbpickport().
>
> Ok ?
OK bluhm@
>
> Index: netinet/in_pcb.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/in_pcb.c,v
> retrieving revision 1.198
> diff -u -p -r1.198 in_pcb.c
> --- netinet/in_pcb.c 26 Mar 2016 21:56:04 -0000 1.198
> +++ netinet/in_pcb.c 3 Apr 2016 19:16:37 -0000
> @@ -286,6 +286,7 @@ in_pcbbind(struct inpcb *inp, struct mbu
> struct socket *so = inp->inp_socket;
> u_int16_t lport = 0;
> int wild = 0;
> + void *laddr = &zeroin46_addr;
> int error;
>
> if (inp->inp_lport)
> @@ -312,9 +313,10 @@ in_pcbbind(struct inpcb *inp, struct mbu
> if (sin6->sin6_family != AF_INET6)
> return (EAFNOSUPPORT);
>
> + wild |= INPLOOKUP_IPV6;
> if ((error = in6_pcbaddrisavail(inp, sin6, wild, p)))
> return (error);
> - inp->inp_laddr6 = sin6->sin6_addr;
> + laddr = &sin6->sin6_addr;
> lport = sin6->sin6_port;
> break;
> }
> @@ -332,7 +334,7 @@ in_pcbbind(struct inpcb *inp, struct mbu
>
> if ((error = in_pcbaddrisavail(inp, sin, wild, p)))
> return (error);
> - inp->inp_laddr = sin->sin_addr;
> + laddr = &sin->sin_addr;
> lport = sin->sin_port;
> break;
> }
> @@ -342,8 +344,20 @@ in_pcbbind(struct inpcb *inp, struct mbu
> }
>
> if (lport == 0)
> - if ((error = in_pcbpickport(&lport, wild, inp, p)))
> + if ((error = in_pcbpickport(&lport, laddr, wild, inp, p)))
> return (error);
> + if (nam) {
> + switch (sotopf(so)) {
> +#ifdef INET6
> + case PF_INET6:
> + inp->inp_laddr6 = *(struct in6_addr *)laddr;
> + break;
> +#endif
> + case PF_INET:
> + inp->inp_laddr = *(struct in_addr *)laddr;
> + break;
> + }
> + }
> inp->inp_lport = lport;
> in_pcbrehash(inp);
> return (0);
> @@ -418,12 +432,12 @@ in_pcbaddrisavail(struct inpcb *inp, str
> }
>
> int
> -in_pcbpickport(u_int16_t *lport, int wild, struct inpcb *inp, struct proc *p)
> +in_pcbpickport(u_int16_t *lport, void *laddr, int wild, struct inpcb *inp,
> + struct proc *p)
> {
> struct socket *so = inp->inp_socket;
> struct inpcbtable *table = inp->inp_table;
> u_int16_t first, last, lower, higher, candidate, localport;
> - void *laddr;
> int count;
>
> if (inp->inp_flags & INP_HIGHPORT) {
> @@ -453,10 +467,6 @@ in_pcbpickport(u_int16_t *lport, int wil
>
> count = higher - lower;
> candidate = lower + arc4random_uniform(count);
> - if (sotopf(so) == PF_INET6)
> - laddr = &inp->inp_laddr6;
> - else
> - laddr = &inp->inp_laddr;
>
> do {
> if (count-- < 0) /* completely used? */
> Index: netinet/in_pcb.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet/in_pcb.h,v
> retrieving revision 1.96
> diff -u -p -r1.96 in_pcb.h
> --- netinet/in_pcb.h 23 Mar 2016 15:50:36 -0000 1.96
> +++ netinet/in_pcb.h 3 Apr 2016 19:16:37 -0000
> @@ -290,6 +290,6 @@ int in6_pcbnotify(struct inpcbtable *, s
> u_int, const struct sockaddr_in6 *, u_int, u_int, int, void *,
> void (*)(struct inpcb *, int));
> int in6_selecthlim(struct inpcb *);
> -int in_pcbpickport(u_int16_t *, int, struct inpcb *, struct proc *);
> +int in_pcbpickport(u_int16_t *, void *, int, struct inpcb *, struct proc *);
> #endif /* _KERNEL */
> #endif /* _NETINET_IN_PCB_H_ */