Revision 05476c4d sysdep/unix/io.c

View differences:

sysdep/unix/io.c
22 22
#include <unistd.h>
23 23
#include <fcntl.h>
24 24
#include <errno.h>
25
#include <net/if.h>
25 26
#include <netinet/in.h>
26 27
#include <netinet/tcp.h>
27 28
#include <netinet/udp.h>
......
470 471
    strcpy(x, "<too-long>");
471 472
}
472 473

  
474

  
473 475
/**
474 476
 * DOC: Sockets
475 477
 *
......
496 498
#endif
497 499

  
498 500

  
499
static list sock_list;
500
static struct birdsock *current_sock;
501
static struct birdsock *stored_sock;
502
static int sock_recalc_fdsets_p;
501
/*
502
 *	Sockaddr helper functions
503
 */
503 504

  
504
static inline sock *
505
sk_next(sock *s)
505
static inline int sockaddr_length(int af)
506
{ return (af == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); }
507

  
508
static inline void
509
sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, struct iface *ifa, uint port)
506 510
{
507
  if (!s->n.next->next)
508
    return NULL;
509
  else
510
    return SKIP_BACK(sock, n, s->n.next);
511
  memset(sa, 0, sizeof(struct sockaddr_in));
512
#ifdef HAVE_SIN_LEN
513
  sa->sin_len = sizeof(struct sockaddr_in);
514
#endif
515
  sa->sin_family = AF_INET;
516
  sa->sin_port = htons(port);
517
  sa->sin_addr = ipa_to_in4(a);
511 518
}
512 519

  
513
static void
514
sk_alloc_bufs(sock *s)
520
static inline void
521
sockaddr_fill6(struct sockaddr_in6 *sa, ip_addr a, struct iface *ifa, uint port)
515 522
{
516
  if (!s->rbuf && s->rbsize)
517
    s->rbuf = s->rbuf_alloc = xmalloc(s->rbsize);
518
  s->rpos = s->rbuf;
519
  if (!s->tbuf && s->tbsize)
520
    s->tbuf = s->tbuf_alloc = xmalloc(s->tbsize);
521
  s->tpos = s->ttx = s->tbuf;
523
  memset(sa, 0, sizeof(struct sockaddr_in6));
524
#ifdef SIN6_LEN
525
  sa->sin6_len = sizeof(struct sockaddr_in6);
526
#endif
527
  sa->sin6_family = AF_INET6;
528
  sa->sin6_port = htons(port);
529
  sa->sin6_flowinfo = 0;
530
  sa->sin6_addr = ipa_to_in6(a);
531

  
532
  if (ifa && ipa_is_link_local(a))
533
    sa->sin6_scope_id = ifa->index;
522 534
}
523 535

  
524
static void
525
sk_free_bufs(sock *s)
536
void
537
sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port)
526 538
{
527
  if (s->rbuf_alloc)
528
    {
529
      xfree(s->rbuf_alloc);
530
      s->rbuf = s->rbuf_alloc = NULL;
531
    }
532
  if (s->tbuf_alloc)
533
    {
534
      xfree(s->tbuf_alloc);
535
      s->tbuf = s->tbuf_alloc = NULL;
536
    }
539
  if (af == AF_INET)
540
    sockaddr_fill4((struct sockaddr_in *) sa, a, ifa, port);
541
  else if (af == AF_INET6)
542
    sockaddr_fill6((struct sockaddr_in6 *) sa, a, ifa, port);
543
  else
544
    bug("Unknown AF");
537 545
}
538 546

  
539
static void
540
sk_free(resource *r)
547
static inline void
548
sockaddr_read4(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, uint *port)
541 549
{
542
  sock *s = (sock *) r;
543

  
544
  sk_free_bufs(s);
545
  if (s->fd >= 0)
546
    {
547
      close(s->fd);
548

  
549
      /* FIXME: we should call sk_stop() for SKF_THREAD sockets */
550
      if (s->flags & SKF_THREAD)
551
	return;
552

  
553
      if (s == current_sock)
554
	current_sock = sk_next(s);
555
      if (s == stored_sock)
556
	stored_sock = sk_next(s);
557
      rem_node(&s->n);
558
      sock_recalc_fdsets_p = 1;
559
    }
550
  *port = ntohs(sa->sin_port);
551
  *a = ipa_from_in4(sa->sin_addr);
560 552
}
561 553

  
562
void
563
sk_set_rbsize(sock *s, uint val)
554
static inline void
555
sockaddr_read6(struct sockaddr_in6 *sa, ip_addr *a, struct iface **ifa, uint *port)
564 556
{
565
  ASSERT(s->rbuf_alloc == s->rbuf);
557
  *port = ntohs(sa->sin6_port);
558
  *a = ipa_from_in6(sa->sin6_addr);
566 559

  
567
  if (s->rbsize == val)
568
    return;
569

  
570
  s->rbsize = val;
571
  xfree(s->rbuf_alloc);
572
  s->rbuf_alloc = xmalloc(val);
573
  s->rpos = s->rbuf = s->rbuf_alloc;
560
  if (ifa && ipa_is_link_local(*a))
561
    *ifa = if_find_by_index(sa->sin6_scope_id);
574 562
}
575 563

  
576
void
577
sk_set_tbsize(sock *s, uint val)
564
int
565
sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port)
578 566
{
579
  ASSERT(s->tbuf_alloc == s->tbuf);
567
  if (sa->sa.sa_family != af)
568
    goto fail;
580 569

  
581
  if (s->tbsize == val)
582
    return;
570
  if (af == AF_INET)
571
    sockaddr_read4((struct sockaddr_in *) sa, a, ifa, port);
572
  else if (af == AF_INET6)
573
    sockaddr_read6((struct sockaddr_in6 *) sa, a, ifa, port);
574
  else
575
    goto fail;
583 576

  
584
  byte *old_tbuf = s->tbuf;
577
  return 0;
585 578

  
586
  s->tbsize = val;
587
  s->tbuf = s->tbuf_alloc = xrealloc(s->tbuf_alloc, val);
588
  s->tpos = s->tbuf + (s->tpos - old_tbuf);
589
  s->ttx  = s->tbuf + (s->ttx  - old_tbuf);
579
 fail:
580
  *a = IPA_NONE;
581
  *port = 0;
582
  return -1;
590 583
}
591 584

  
592
void
593
sk_set_tbuf(sock *s, void *tbuf)
594
{
595
  s->tbuf = tbuf ?: s->tbuf_alloc;
596
  s->ttx = s->tpos = s->tbuf;
597
}
598 585

  
599
void
600
sk_reallocate(sock *s)
601
{
602
  sk_free_bufs(s);
603
  sk_alloc_bufs(s);
604
}
586
/*
587
 *	IPv6 multicast syscalls
588
 */
605 589

  
606
static void
607
sk_dump(resource *r)
608
{
609
  sock *s = (sock *) r;
610
  static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", "UDP/MC", "IP", "IP/MC", "MAGIC", "UNIX<", "UNIX", "DEL!" };
590
/* Fortunately standardized in RFC 3493 */
611 591

  
612
  debug("(%s, ud=%p, sa=%08x, sp=%d, da=%08x, dp=%d, tos=%d, ttl=%d, if=%s)\n",
613
	sk_type_names[s->type],
614
	s->data,
615
	s->saddr,
616
	s->sport,
617
	s->daddr,
618
	s->dport,
619
	s->tos,
620
	s->ttl,
621
	s->iface ? s->iface->name : "none");
622
}
623

  
624
static struct resclass sk_class = {
625
  "Socket",
626
  sizeof(sock),
627
  sk_free,
628
  sk_dump,
629
  NULL,
630
  NULL
631
};
592
#define INIT_MREQ6(maddr,ifa) \
593
  { .ipv6mr_multiaddr = ipa_to_in6(maddr), .ipv6mr_interface = ifa->index }
632 594

  
633
/**
634
 * sk_new - create a socket
635
 * @p: pool
636
 *
637
 * This function creates a new socket resource. If you want to use it,
638
 * you need to fill in all the required fields of the structure and
639
 * call sk_open() to do the actual opening of the socket.
640
 *
641
 * The real function name is sock_new(), sk_new() is a macro wrapper
642
 * to avoid collision with OpenSSL.
643
 */
644
sock *
645
sock_new(pool *p)
595
static inline int
596
sk_setup_multicast6(sock *s)
646 597
{
647
  sock *s = ralloc(p, &sk_class);
648
  s->pool = p;
649
  // s->saddr = s->daddr = IPA_NONE;
650
  s->tos = s->priority = s->ttl = -1;
651
  s->fd = -1;
652
  return s;
653
}
598
  int index = s->iface->index;
599
  int ttl = s->ttl;
600
  int n = 0;
654 601

  
655
static void
656
sk_insert(sock *s)
657
{
658
  add_tail(&sock_list, &s->n);
659
  sock_recalc_fdsets_p = 1;
660
}
602
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) < 0)
603
    ERR("IPV6_MULTICAST_IF");
661 604

  
662
#ifdef IPV6
605
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0)
606
    ERR("IPV6_MULTICAST_HOPS");
663 607

  
664
void
665
fill_in_sockaddr(struct sockaddr_in6 *sa, ip_addr a, struct iface *ifa, unsigned port)
666
{
667
  memset(sa, 0, sizeof (struct sockaddr_in6));
668
  sa->sin6_family = AF_INET6;
669
  sa->sin6_port = htons(port);
670
  sa->sin6_flowinfo = 0;
671
#ifdef HAVE_SIN_LEN
672
  sa->sin6_len = sizeof(struct sockaddr_in6);
673
#endif
674
  set_inaddr(&sa->sin6_addr, a);
608
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &n, sizeof(n)) < 0)
609
    ERR("IPV6_MULTICAST_LOOP");
675 610

  
676
  if (ifa && ipa_has_link_scope(a))
677
    sa->sin6_scope_id = ifa->index;
611
  return 0;
678 612
}
679 613

  
680
void
681
get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check)
614
static inline int
615
sk_join_group6(sock *s, ip_addr maddr)
682 616
{
683
  if (check && sa->sin6_family != AF_INET6)
684
    bug("get_sockaddr called for wrong address family (%d)", sa->sin6_family);
685
  if (port)
686
    *port = ntohs(sa->sin6_port);
687
  memcpy(a, &sa->sin6_addr, sizeof(*a));
688
  ipa_ntoh(*a);
617
  struct ipv6_mreq mr = INIT_MREQ6(maddr, s->iface);
689 618

  
690
  if (ifa && ipa_has_link_scope(*a))
691
    *ifa = if_find_by_index(sa->sin6_scope_id);
692
}
619
  if (setsockopt(s->fd, SOL_IPV6, IPV6_JOIN_GROUP, &mr, sizeof(mr)) < 0)
620
    ERR("IPV6_JOIN_GROUP");
693 621

  
694
#else
695

  
696
void
697
fill_in_sockaddr(struct sockaddr_in *sa, ip_addr a, struct iface *ifa, unsigned port)
698
{
699
  memset (sa, 0, sizeof (struct sockaddr_in));
700
  sa->sin_family = AF_INET;
701
  sa->sin_port = htons(port);
702
#ifdef HAVE_SIN_LEN
703
  sa->sin_len = sizeof(struct sockaddr_in);
704
#endif
705
  set_inaddr(&sa->sin_addr, a);
622
  return 0;
706 623
}
707 624

  
708
void
709
get_sockaddr(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check)
625
static inline int
626
sk_leave_group6(sock *s, ip_addr maddr)
710 627
{
711
  if (check && sa->sin_family != AF_INET)
712
    bug("get_sockaddr called for wrong address family (%d)", sa->sin_family);
713
  if (port)
714
    *port = ntohs(sa->sin_port);
715
  memcpy(a, &sa->sin_addr.s_addr, sizeof(*a));
716
  ipa_ntoh(*a);
717
}
628
  struct ipv6_mreq mr = INIT_MREQ6(maddr, s->iface);
718 629

  
719
#endif
630
  if (setsockopt(s->fd, SOL_IPV6, IPV6_LEAVE_GROUP, &mr, sizeof(mr)) < 0)
631
    ERR("IPV6_LEAVE_GROUP");
632

  
633
  return 0;
634
}
720 635

  
721 636

  
722
#ifdef IPV6
637
/*
638
 *	IPv6 packet control messages
639
 */
723 640

  
724
/* PKTINFO handling is also standardized in IPv6 */
725
#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)))
726
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in6_pktinfo))
641
/* Also standardized, in RFC 3542 */
727 642

  
728 643
/*
729 644
 * RFC 2292 uses IPV6_PKTINFO for both the socket option and the cmsg
......
741 656
#define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
742 657
#endif
743 658

  
744
static char *
745
sysio_register_cmsgs(sock *s)
746
{
747
  int ok = 1;
748 659

  
749
  if ((s->flags & SKF_LADDR_RX) &&
750
      (setsockopt(s->fd, SOL_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0))
751
    return "IPV6_RECVPKTINFO";
660
#define CMSG6_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in6_pktinfo))
661
#define CMSG6_SPACE_TTL CMSG_SPACE(sizeof(int))
752 662

  
753
  if ((s->flags & SKF_TTL_RX) &&
754
      (setsockopt(s->fd, SOL_IPV6, IPV6_RECVHOPLIMIT, &ok, sizeof(ok)) < 0))
755
    return "IPV6_RECVHOPLIMIT";
663
static inline int
664
sk_request_cmsg6_pktinfo(sock *s)
665
{
666
  int y = 1;
756 667

  
757
  return NULL;
668
  if (setsockopt(s->fd, SOL_IPV6, IPV6_RECVPKTINFO, &y, sizeof(y)) < 0)
669
    ERR("IPV6_RECVPKTINFO");
670

  
671
  return 0;
758 672
}
759 673

  
760
static void
761
sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
674
static inline int
675
sk_request_cmsg6_ttl(sock *s)
762 676
{
763
  struct cmsghdr *cm;
764
  struct in6_pktinfo *pi = NULL;
765
  int *hlim = NULL;
677
  int y = 1;
766 678

  
767
  for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
768
  {
769
    if (cm->cmsg_level == SOL_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
770
      pi = (struct in6_pktinfo *) CMSG_DATA(cm);
679
  if (setsockopt(s->fd, SOL_IPV6, IPV6_RECVHOPLIMIT, &y, sizeof(y)) < 0)
680
    ERR("IPV6_RECVHOPLIMIT");
771 681

  
772
    if (cm->cmsg_level == SOL_IPV6 && cm->cmsg_type == IPV6_HOPLIMIT)
773
      hlim = (int *) CMSG_DATA(cm);
774
  }
682
  return 0;
683
}
775 684

  
776
  if (s->flags & SKF_LADDR_RX)
685
static inline void
686
sk_process_cmsg6_pktinfo(sock *s, struct cmsghdr *cm)
687
{
688
  if (cm->cmsg_type == IPV6_PKTINFO)
777 689
  {
778
    if (pi)
779
    {
780
      get_inaddr(&s->laddr, &pi->ipi6_addr);
781
      s->lifindex = pi->ipi6_ifindex;
782
    }
783
    else
784
    {
785
      s->laddr = IPA_NONE;
786
      s->lifindex = 0;
787
    }
690
    struct in6_pktinfo *pi = (struct in6_pktinfo *) CMSG_DATA(cm);
691
    s->laddr = ipa_from_in6(pi->ipi6_addr);
692
    s->lifindex = pi->ipi6_ifindex;
788 693
  }
694
}
789 695

  
790
  if (s->flags & SKF_TTL_RX)
791
    s->ttl = hlim ? *hlim : -1;
792

  
793
  return;
696
static inline void
697
sk_process_cmsg6_ttl(sock *s, struct cmsghdr *cm)
698
{
699
  if (cm->cmsg_type == IPV6_HOPLIMIT)
700
    s->rcv_ttl = * (int *) CMSG_DATA(cm);
794 701
}
795 702

  
796
static void
797
sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
703
static inline void
704
sk_prepare_cmsgs6(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
798 705
{
799 706
  struct cmsghdr *cm;
800 707
  struct in6_pktinfo *pi;
......
809 716

  
810 717
  pi = (struct in6_pktinfo *) CMSG_DATA(cm);
811 718
  pi->ipi6_ifindex = s->iface ? s->iface->index : 0;
812
  set_inaddr(&pi->ipi6_addr, s->saddr);
719
  pi->ipi6_addr = ipa_to_in6(s->saddr);
813 720

  
814 721
  msg->msg_controllen = cm->cmsg_len;
815 722
}
816 723

  
817
#endif
818 724

  
819
static char *
820
sk_set_ttl_int(sock *s)
725
/*
726
 *	Miscellaneous socket syscalls
727
 */
728

  
729
static inline int
730
sk_set_ttl4(sock *s, int ttl)
821 731
{
822
#ifdef IPV6
823
  if (setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
824
    return "IPV6_UNICAST_HOPS";
825
#else
826
  if (setsockopt(s->fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
827
    return "IP_TTL";
828
#endif
829
  return NULL;
732
  if (setsockopt(s->fd, SOL_IP, IP_TTL, &ttl, sizeof(ttl)) < 0)
733
    ERR("IP_TTL");
734

  
735
  return 0;
830 736
}
831 737

  
832
#define ERR(x) do { err = x; goto bad; } while(0)
833
#define WARN(x) log(L_WARN "sk_setup: %s: %m", x)
738
static inline int
739
sk_set_ttl6(sock *s, int ttl)
740
{
741
  if (setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0)
742
    ERR("IPV6_UNICAST_HOPS");
834 743

  
835
static char *
836
sk_setup(sock *s)
744
  return 0;
745
}
746

  
747
static inline int
748
sk_set_tos4(sock *s, int tos)
837 749
{
838
  int one = 1;
839
  int fd = s->fd;
840
  char *err = NULL;
750
  if (setsockopt(s->fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
751
    ERR("IP_TOS");
841 752

  
842
  if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
843
    ERR("fcntl(O_NONBLOCK)");
844
  if (s->type == SK_UNIX)
845
    return NULL;
753
  return 0;
754
}
846 755

  
847
  if (ipa_nonzero(s->saddr) && !(s->flags & SKF_BIND))
848
    s->flags |= SKF_PKTINFO;
756
static inline int
757
sk_set_tos6(sock *s, int tos)
758
{
759
  if (setsockopt(s->fd, SOL_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0)
760
    ERR("IPV6_TCLASS");
849 761

  
850
#ifdef CONFIG_USE_HDRINCL
851
  if ((s->type == SK_IP) && (s->flags & SKF_PKTINFO))
852
  {
853
    s->flags &= ~SKF_PKTINFO;
854
    s->flags |= SKF_HDRINCL;
855
    if (setsockopt(fd, SOL_IP, IP_HDRINCL, &one, sizeof(one)) < 0)
856
      ERR("IP_HDRINCL");
857
  }
858
#endif
762
  return 0;
763
}
859 764

  
860
  if (s->iface)
861
  {
862
#ifdef SO_BINDTODEVICE
863
    struct ifreq ifr;
864
    strcpy(ifr.ifr_name, s->iface->name);
865
    if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
866
      ERR("SO_BINDTODEVICE");
867
#endif
868 765

  
869
#ifdef CONFIG_UNIX_DONTROUTE
870
    if (setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
871
      ERR("SO_DONTROUTE");
872
#endif
873
  }
766
/*
767
 *	Public socket functions
768
 */
874 769

  
875
  if ((s->ttl >= 0) && (err = sk_set_ttl_int(s)))
876
    goto bad;
770
/**
771
 * sk_setup_multicast - enable multicast for given socket
772
 * @s: socket
773
 *
774
 * Prepare transmission of multicast packets for given datagram socket.
775
 * The socket must have defined @iface.
776
 *
777
 * Result: 0 for success, -1 for an error.
778
 */
877 779

  
878
  if (err = sysio_register_cmsgs(s))
879
    goto bad;
780
int
781
sk_setup_multicast(sock *s)
782
{
783
  ASSERT(s->iface);
880 784

  
785
  if (sk_is_ipv4(s))
786
    return sk_setup_multicast4(s);
787
  else
788
    return sk_setup_multicast6(s);
789
}
881 790

  
882
#ifdef IPV6
883
  if ((s->tos >= 0) && setsockopt(fd, SOL_IPV6, IPV6_TCLASS, &s->tos, sizeof(s->tos)) < 0)
884
    WARN("IPV6_TCLASS");
885
#else
886
  if ((s->tos >= 0) && setsockopt(fd, SOL_IP, IP_TOS, &s->tos, sizeof(s->tos)) < 0)
887
    WARN("IP_TOS");
888
#endif
791
/**
792
 * sk_join_group - join multicast group for given socket
793
 * @s: socket
794
 * @maddr: multicast address
795
 *
796
 * Join multicast group for given datagram socket and associated interface.
797
 * The socket must have defined @iface.
798
 *
799
 * Result: 0 for success, -1 for an error.
800
 */
889 801

  
890
  if (s->priority >= 0)
891
    sk_set_priority(s, s->priority);
802
int
803
sk_join_group(sock *s, ip_addr maddr)
804
{
805
  if (sk_is_ipv4(s))
806
    return sk_join_group4(s, maddr);
807
  else
808
    return sk_join_group6(s, maddr);
809
}
892 810

  
893
#ifdef IPV6
894
  if ((s->flags & SKF_V6ONLY) && setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &one, sizeof(one)) < 0)
895
    WARN("IPV6_V6ONLY");
896
#endif
811
/**
812
 * sk_leave_group - leave multicast group for given socket
813
 * @s: socket
814
 * @maddr: multicast address
815
 *
816
 * Leave multicast group for given datagram socket and associated interface.
817
 * The socket must have defined @iface.
818
 *
819
 * Result: 0 for success, -1 for an error.
820
 */
821

  
822
int
823
sk_leave_group(sock *s, ip_addr maddr)
824
{
825
  if (sk_is_ipv4(s))
826
    return sk_leave_group4(s, maddr);
827
  else
828
    return sk_leave_group6(s, maddr);
829
}
830

  
831
/**
832
 * sk_setup_broadcast - enable broadcast for given socket
833
 * @s: socket
834
 *
835
 * Allow reception and transmission of broadcast packets for given datagram
836
 * socket. The socket must have defined @iface. For transmission, packets should
837
 * be send to @brd address of @iface.
838
 *
839
 * Result: 0 for success, -1 for an error.
840
 */
897 841

  
898
bad:
899
  return err;
842
int
843
sk_setup_broadcast(sock *s)
844
{
845
  int y = 1;
846

  
847
  if (setsockopt(s->fd, SOL_SOCKET, SO_BROADCAST, &y, sizeof(y)) < 0)
848
    ERR("SO_BROADCAST");
849

  
850
  return 0;
900 851
}
901 852

  
902 853
/**
903
 * sk_set_ttl - set transmit TTL for given socket.
854
 * sk_set_ttl - set transmit TTL for given socket
904 855
 * @s: socket
905 856
 * @ttl: TTL value
906 857
 *
907
 * Set TTL for already opened connections when TTL was not set before.
908
 * Useful for accepted connections when different ones should have 
909
 * different TTL.
858
 * Set TTL for already opened connections when TTL was not set before. Useful
859
 * for accepted connections when different ones should have different TTL.
910 860
 *
911 861
 * Result: 0 for success, -1 for an error.
912 862
 */
......
914 864
int
915 865
sk_set_ttl(sock *s, int ttl)
916 866
{
917
  char *err;
918

  
919 867
  s->ttl = ttl;
920
  if (err = sk_set_ttl_int(s))
921
    log(L_ERR "sk_set_ttl: %s: %m", err);
922 868

  
923
  return (err ? -1 : 0);
869
  if (sk_is_ipv4(s))
870
    return sk_set_ttl4(s, ttl);
871
  else
872
    return sk_set_ttl6(s, ttl);
924 873
}
925 874

  
926 875
/**
927
 * sk_set_min_ttl - set minimal accepted TTL for given socket.
876
 * sk_set_min_ttl - set minimal accepted TTL for given socket
928 877
 * @s: socket
929 878
 * @ttl: TTL value
930 879
 *
931
 * Can be used in TTL security implementation
880
 * Set minimal accepted TTL for given socket. Can be used for TTL security.
881
 * implementations.
932 882
 *
933 883
 * Result: 0 for success, -1 for an error.
934 884
 */
......
936 886
int
937 887
sk_set_min_ttl(sock *s, int ttl)
938 888
{
939
  int err;
940
#ifdef IPV6
941
  err = sk_set_min_ttl6(s, ttl);
942
#else
943
  err = sk_set_min_ttl4(s, ttl);
944
#endif
945

  
946
  return err;
889
  if (sk_is_ipv4(s))
890
    return sk_set_min_ttl4(s, ttl);
891
  else
892
    return sk_set_min_ttl6(s, ttl);
947 893
}
948 894

  
895
#if 0
949 896
/**
950
 * sk_set_md5_auth - add / remove MD5 security association for given socket.
897
 * sk_set_md5_auth - add / remove MD5 security association for given socket
951 898
 * @s: socket
952 899
 * @a: IP address of the other side
953 900
 * @ifa: Interface for link-local IP address
954 901
 * @passwd: password used for MD5 authentication
955 902
 *
956
 * In TCP MD5 handling code in kernel, there is a set of pairs
957
 * (address, password) used to choose password according to
958
 * address of the other side. This function is useful for
959
 * listening socket, for active sockets it is enough to set
960
 * s->password field.
903
 * In TCP MD5 handling code in kernel, there is a set of pairs (address,
904
 * password) used to choose password according to address of the other side.
905
 * This function is useful for listening socket, for active sockets it is enough
906
 * to set s->password field.
961 907
 *
962 908
 * When called with passwd != NULL, the new pair is added,
963 909
 * When called with passwd == NULL, the existing pair is removed.
......
967 913

  
968 914
int
969 915
sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
970
{
971
  sockaddr sa;
972
  fill_in_sockaddr(&sa, a, ifa, 0);
973
  return sk_set_md5_auth_int(s, &sa, passwd);
974
}
975

  
976
int
977
sk_set_broadcast(sock *s, int enable)
978
{
979
  if (setsockopt(s->fd, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable)) < 0)
980
    {
981
      log(L_ERR "sk_set_broadcast: SO_BROADCAST: %m");
982
      return -1;
983
    }
984

  
985
  return 0;
986
}
987

  
916
{ DUMMY; }
917
#endif
988 918

  
989
#ifdef IPV6
919
/**
920
 * sk_set_ipv6_checksum - specify IPv6 checksum offset for given socket
921
 * @s: socket
922
 * @offset: offset
923
 *
924
 * Specify IPv6 checksum field offset for given raw IPv6 socket. After that, the
925
 * kernel will automatically fill it for outgoing packets and check it for
926
 * incoming packets. Should not be used on ICMPv6 sockets, where the position is
927
 * known to the kernel.
928
 *
929
 * Result: 0 for success, -1 for an error.
930
 */
990 931

  
991 932
int
992 933
sk_set_ipv6_checksum(sock *s, int offset)
993 934
{
994 935
  if (setsockopt(s->fd, SOL_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) < 0)
995
    {
996
      log(L_ERR "sk_set_ipv6_checksum: IPV6_CHECKSUM: %m");
997
      return -1;
998
    }
936
    ERR("IPV6_CHECKSUM");
999 937

  
1000 938
  return 0;
1001 939
}
1002 940

  
1003 941
int
1004
sk_set_icmp_filter(sock *s, int p1, int p2)
942
sk_set_icmp6_filter(sock *s, int p1, int p2)
1005 943
{
1006 944
  /* a bit of lame interface, but it is here only for Radv */
1007 945
  struct icmp6_filter f;
......
1011 949
  ICMP6_FILTER_SETPASS(p2, &f);
1012 950

  
1013 951
  if (setsockopt(s->fd, SOL_ICMPV6, ICMP6_FILTER, &f, sizeof(f)) < 0)
1014
    {
1015
      log(L_ERR "sk_setup_icmp_filter: ICMP6_FILTER: %m");
1016
      return -1;
1017
    }
952
    ERR("ICMP6_FILTER");
1018 953

  
1019 954
  return 0;
1020 955
}
1021 956

  
1022
int
1023
sk_setup_multicast(sock *s)
957
void
958
sk_log_error(sock *s, const char *p)
959
{
960
  log(L_ERR "%s: Socket error: %s%#m", p, s->err);
961
}
962

  
963

  
964
/*
965
 *	Actual struct birdsock code
966
 */
967

  
968
static list sock_list;
969
static struct birdsock *current_sock;
970
static struct birdsock *stored_sock;
971
static int sock_recalc_fdsets_p;
972

  
973
static inline sock *
974
sk_next(sock *s)
975
{
976
  if (!s->n.next->next)
977
    return NULL;
978
  else
979
    return SKIP_BACK(sock, n, s->n.next);
980
}
981

  
982
static void
983
sk_alloc_bufs(sock *s)
984
{
985
  if (!s->rbuf && s->rbsize)
986
    s->rbuf = s->rbuf_alloc = xmalloc(s->rbsize);
987
  s->rpos = s->rbuf;
988
  if (!s->tbuf && s->tbsize)
989
    s->tbuf = s->tbuf_alloc = xmalloc(s->tbsize);
990
  s->tpos = s->ttx = s->tbuf;
991
}
992

  
993
static void
994
sk_free_bufs(sock *s)
995
{
996
  if (s->rbuf_alloc)
997
  {
998
    xfree(s->rbuf_alloc);
999
    s->rbuf = s->rbuf_alloc = NULL;
1000
  }
1001
  if (s->tbuf_alloc)
1002
  {
1003
    xfree(s->tbuf_alloc);
1004
    s->tbuf = s->tbuf_alloc = NULL;
1005
  }
1006
}
1007

  
1008
static void
1009
sk_free(resource *r)
1010
{
1011
  sock *s = (sock *) r;
1012

  
1013
  sk_free_bufs(s);
1014
  if (s->fd >= 0)
1015
  {
1016
    close(s->fd);
1017

  
1018
    /* FIXME: we should call sk_stop() for SKF_THREAD sockets */
1019
    if (s->flags & SKF_THREAD)
1020
      return;
1021

  
1022
    if (s == current_sock)
1023
      current_sock = sk_next(s);
1024
    if (s == stored_sock)
1025
      stored_sock = sk_next(s);
1026
    rem_node(&s->n);
1027
    sock_recalc_fdsets_p = 1;
1028
  }
1029
}
1030

  
1031
void
1032
sk_set_rbsize(sock *s, uint val)
1033
{
1034
  ASSERT(s->rbuf_alloc == s->rbuf);
1035

  
1036
  if (s->rbsize == val)
1037
    return;
1038

  
1039
  s->rbsize = val;
1040
  xfree(s->rbuf_alloc);
1041
  s->rbuf_alloc = xmalloc(val);
1042
  s->rpos = s->rbuf = s->rbuf_alloc;
1043
}
1044

  
1045
void
1046
sk_set_tbsize(sock *s, uint val)
1047
{
1048
  ASSERT(s->tbuf_alloc == s->tbuf);
1049

  
1050
  if (s->tbsize == val)
1051
    return;
1052

  
1053
  byte *old_tbuf = s->tbuf;
1054

  
1055
  s->tbsize = val;
1056
  s->tbuf = s->tbuf_alloc = xrealloc(s->tbuf_alloc, val);
1057
  s->tpos = s->tbuf + (s->tpos - old_tbuf);
1058
  s->ttx  = s->tbuf + (s->ttx  - old_tbuf);
1059
}
1060

  
1061
void
1062
sk_set_tbuf(sock *s, void *tbuf)
1063
{
1064
  s->tbuf = tbuf ?: s->tbuf_alloc;
1065
  s->ttx = s->tpos = s->tbuf;
1066
}
1067

  
1068
void
1069
sk_reallocate(sock *s)
1070
{
1071
  sk_free_bufs(s);
1072
  sk_alloc_bufs(s);
1073
}
1074

  
1075
static void
1076
sk_dump(resource *r)
1077
{
1078
  sock *s = (sock *) r;
1079
  static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", NULL, "IP", NULL, "MAGIC", "UNIX<", "UNIX", "DEL!" };
1080

  
1081
  debug("(%s, ud=%p, sa=%08x, sp=%d, da=%08x, dp=%d, tos=%d, ttl=%d, if=%s)\n",
1082
	sk_type_names[s->type],
1083
	s->data,
1084
	s->saddr,
1085
	s->sport,
1086
	s->daddr,
1087
	s->dport,
1088
	s->tos,
1089
	s->ttl,
1090
	s->iface ? s->iface->name : "none");
1091
}
1092

  
1093
static struct resclass sk_class = {
1094
  "Socket",
1095
  sizeof(sock),
1096
  sk_free,
1097
  sk_dump,
1098
  NULL,
1099
  NULL
1100
};
1101

  
1102
/**
1103
 * sk_new - create a socket
1104
 * @p: pool
1105
 *
1106
 * This function creates a new socket resource. If you want to use it,
1107
 * you need to fill in all the required fields of the structure and
1108
 * call sk_open() to do the actual opening of the socket.
1109
 *
1110
 * The real function name is sock_new(), sk_new() is a macro wrapper
1111
 * to avoid collision with OpenSSL.
1112
 */
1113
sock *
1114
sock_new(pool *p)
1115
{
1116
  sock *s = ralloc(p, &sk_class);
1117
  s->pool = p;
1118
  // s->saddr = s->daddr = IPA_NONE;
1119
  s->tos = s->priority = s->ttl = -1;
1120
  s->fd = -1;
1121
  return s;
1122
}
1123

  
1124
static int
1125
sk_setup(sock *s)
1024 1126
{
1025
  char *err;
1026
  int zero = 0;
1027
  int index;
1028

  
1029
  ASSERT(s->iface);
1127
  int y = 1;
1128
  int fd = s->fd;
1030 1129

  
1031
  index = s->iface->index;
1032
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
1033
    ERR("IPV6_MULTICAST_HOPS");
1034
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
1035
    ERR("IPV6_MULTICAST_LOOP");
1036
  if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) < 0)
1037
    ERR("IPV6_MULTICAST_IF");
1130
  if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
1131
    ERR("O_NONBLOCK");
1038 1132

  
1039
  return 0;
1133
  if (!s->af)
1134
    return 0;
1040 1135

  
1041
bad:
1042
  log(L_ERR "sk_setup_multicast: %s: %m", err);
1043
  return -1;
1044
}
1136
  if (ipa_nonzero(s->saddr) && !(s->flags & SKF_BIND))
1137
    s->flags |= SKF_PKTINFO;
1045 1138

  
1046
#ifdef CONFIG_IPV6_GLIBC_20
1047
#define ipv6mr_interface ipv6mr_ifindex
1139
#ifdef CONFIG_USE_HDRINCL
1140
  if (sk_is_ipv4(s) && (s->type == SK_IP) && (s->flags & SKF_PKTINFO))
1141
  {
1142
    s->flags &= ~SKF_PKTINFO;
1143
    s->flags |= SKF_HDRINCL;
1144
    if (setsockopt(fd, SOL_IP, IP_HDRINCL, &y, sizeof(y)) < 0)
1145
      ERR("IP_HDRINCL");
1146
  }
1048 1147
#endif
1049 1148

  
1050
int
1051
sk_join_group(sock *s, ip_addr maddr)
1052
{
1053
  struct ipv6_mreq mreq;
1149
  if (s->iface)
1150
  {
1151
#ifdef SO_BINDTODEVICE
1152
    struct ifreq ifr;
1153
    strcpy(ifr.ifr_name, s->iface->name);
1154
    if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
1155
      ERR("SO_BINDTODEVICE");
1156
#endif
1054 1157

  
1055
  set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
1056
  mreq.ipv6mr_interface = s->iface->index;
1158
#ifdef CONFIG_UNIX_DONTROUTE
1159
    if (setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &y, sizeof(y)) < 0)
1160
      ERR("SO_DONTROUTE");
1161
#endif
1162
  }
1057 1163

  
1058
  if (setsockopt(s->fd, SOL_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0)
1059
    {
1060
      log(L_ERR "sk_join_group: IPV6_JOIN_GROUP: %m");
1164
  if (s->priority >= 0)
1165
    if (sk_set_priority(s, s->priority) < 0)
1061 1166
      return -1;
1062
    }
1063 1167

  
1064
  return 0;
1065
}
1168
  if (sk_is_ipv4(s))
1169
  {
1170
    if (s->flags & SKF_LADDR_RX)
1171
      if (sk_request_cmsg4_pktinfo(s) < 0)
1172
	return -1;
1066 1173

  
1067
int
1068
sk_leave_group(sock *s, ip_addr maddr)
1069
{
1070
  struct ipv6_mreq mreq;
1071
	
1072
  set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
1073
  mreq.ipv6mr_interface = s->iface->index;
1174
    if (s->flags & SKF_TTL_RX)
1175
      if (sk_request_cmsg4_ttl(s) < 0)
1176
	return -1;
1074 1177

  
1075
  if (setsockopt(s->fd, SOL_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)) < 0)
1076
    {
1077
      log(L_ERR "sk_leave_group: IPV6_LEAVE_GROUP: %m");
1078
      return -1;
1079
    }
1178
    if ((s->type == SK_UDP) || (s->type == SK_IP))
1179
      if (sk_disable_mtu_disc4(s) < 0)
1180
	return -1;
1080 1181

  
1081
  return 0;
1082
}
1182
    if (s->ttl >= 0)
1183
      if (sk_set_ttl4(s, s->ttl) < 0)
1184
	return -1;
1083 1185

  
1084
#else /* IPV4 */
1186
    if (s->tos >= 0)
1187
      if (sk_set_tos4(s, s->tos) < 0)
1188
	return -1;
1189
  }
1085 1190

  
1086
int
1087
sk_setup_multicast(sock *s)
1088
{
1089
  char *err;
1191
  if (sk_is_ipv6(s))
1192
  {
1193
    if (s->flags & SKF_V6ONLY)
1194
      if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &y, sizeof(y)) < 0)
1195
	ERR("IPV6_V6ONLY");
1090 1196

  
1091
  ASSERT(s->iface);
1197
    if (s->flags & SKF_LADDR_RX)
1198
      if (sk_request_cmsg6_pktinfo(s) < 0)
1199
	return -1;
1092 1200

  
1093
  if (err = sysio_setup_multicast(s))
1094
    {
1095
      log(L_ERR "sk_setup_multicast: %s: %m", err);
1096
      return -1;
1097
    }
1201
    if (s->flags & SKF_TTL_RX)
1202
      if (sk_request_cmsg6_ttl(s) < 0)
1203
	return -1;
1098 1204

  
1099
  return 0;
1100
}
1205
    if ((s->type == SK_UDP) || (s->type == SK_IP))
1206
      if (sk_disable_mtu_disc6(s) < 0)
1207
	return -1;
1101 1208

  
1102
int
1103
sk_join_group(sock *s, ip_addr maddr)
1104
{
1105
 char *err;
1209
    if (s->ttl >= 0)
1210
      if (sk_set_ttl6(s, s->ttl) < 0)
1211
	return -1;
1106 1212

  
1107
 if (err = sysio_join_group(s, maddr))
1108
    {
1109
      log(L_ERR "sk_join_group: %s: %m", err);
1110
      return -1;
1111
    }
1213
    if (s->tos >= 0)
1214
      if (sk_set_tos6(s, s->tos) < 0)
1215
	return -1;
1216
  }
1112 1217

  
1113 1218
  return 0;
1114 1219
}
1115 1220

  
1116
int
1117
sk_leave_group(sock *s, ip_addr maddr)
1221
static void
1222
sk_insert(sock *s)
1118 1223
{
1119
 char *err;
1120

  
1121
 if (err = sysio_leave_group(s, maddr))
1122
    {
1123
      log(L_ERR "sk_leave_group: %s: %m", err);
1124
      return -1;
1125
    }
1126

  
1127
  return 0;
1224
  add_tail(&sock_list, &s->n);
1225
  sock_recalc_fdsets_p = 1;
1128 1226
}
1129 1227

  
1130
#endif 
1131

  
1132

  
1133 1228
static void
1134 1229
sk_tcp_connected(sock *s)
1135 1230
{
1136
  sockaddr lsa;
1137
  int lsa_len = sizeof(lsa);
1138
  if (getsockname(s->fd, (struct sockaddr *) &lsa, &lsa_len) == 0)
1139
    get_sockaddr(&lsa, &s->saddr, &s->iface, &s->sport, 1);
1231
  sockaddr sa;
1232
  int sa_len = sizeof(sa);
1233

  
1234
  if ((getsockname(s->fd, &sa.sa, &sa_len) < 0) ||
1235
      (sockaddr_read(&sa, s->af, &s->saddr, &s->iface, &s->sport) < 0))
1236
    log(L_WARN "SOCK: Cannot get local IP address for TCP>");
1140 1237

  
1141 1238
  s->type = SK_TCP;
1142 1239
  sk_alloc_bufs(s);
......
1144 1241
}
1145 1242

  
1146 1243
static int
1147
sk_passive_connected(sock *s, struct sockaddr *sa, int al, int type)
1244
sk_passive_connected(sock *s, int type)
1148 1245
{
1149
  int fd = accept(s->fd, sa, &al);
1150
  if (fd >= 0)
1151
    {
1152
      sock *t = sk_new(s->pool);
1153
      char *err;
1154
      t->type = type;
1155
      t->fd = fd;
1156
      t->ttl = s->ttl;
1157
      t->tos = s->tos;
1158
      t->rbsize = s->rbsize;
1159
      t->tbsize = s->tbsize;
1160
      if (type == SK_TCP)
1161
	{
1162
	  sockaddr lsa;
1163
	  int lsa_len = sizeof(lsa);
1164
	  if (getsockname(fd, (struct sockaddr *) &lsa, &lsa_len) == 0)
1165
	    get_sockaddr(&lsa, &t->saddr, &t->iface, &t->sport, 1);
1246
  sockaddr loc_sa, rem_sa;
1247
  int loc_sa_len = sizeof(loc_sa);
1248
  int rem_sa_len = sizeof(rem_sa);
1166 1249

  
1167
	  get_sockaddr((sockaddr *) sa, &t->daddr, &t->iface, &t->dport, 1);
1168
	}
1169
      sk_insert(t);
1170
      if (err = sk_setup(t))
1171
	{
1172
	  log(L_ERR "Incoming connection: %s: %m", err);
1173
	  rfree(t);
1174
	  return 1;
1175
	}
1176
      sk_alloc_bufs(t);
1177
      s->rx_hook(t, 0);
1178
      return 1;
1179
    }
1180
  else if (errno != EINTR && errno != EAGAIN)
1181
    {
1250
  int fd = accept(s->fd, ((type == SK_TCP) ? &rem_sa.sa : NULL), &rem_sa_len);
1251
  if (fd < 0)
1252
  {
1253
    if ((errno != EINTR) && (errno != EAGAIN))
1182 1254
      s->err_hook(s, errno);
1183
    }
1184
  return 0;
1255
    return 0;
1256
  }
1257

  
1258
  sock *t = sk_new(s->pool);
1259
  t->type = type;
1260
  t->fd = fd;
1261
  t->af = s->af;
1262
  t->ttl = s->ttl;
1263
  t->tos = s->tos;
1264
  t->rbsize = s->rbsize;
1265
  t->tbsize = s->tbsize;
1266

  
1267
  if (type == SK_TCP)
1268
  {
1269
    if ((getsockname(fd, &loc_sa.sa, &loc_sa_len) < 0) ||
1270
	(sockaddr_read(&loc_sa, s->af, &t->saddr, &t->iface, &t->sport) < 0))
1271
      log(L_WARN "SOCK: Cannot get local IP address for TCP<");
1272

  
1273
    if (sockaddr_read(&rem_sa, s->af, &t->daddr, &t->iface, &t->dport) < 0)
1274
      log(L_WARN "SOCK: Cannot get remote IP address for TCP<");
1275
  }
1276

  
1277
  if (sk_setup(t) < 0)
1278
  {
1279
    /* FIXME: Call err_hook instead ? */
1280
    log(L_ERR "SOCK: Incoming connection: %s%#m", t->err);
1281

  
1282
    /* FIXME: handle it better in rfree() */
1283
    close(t->fd);	
1284
    t->fd = -1;
1285
    rfree(t);
1286
    return 1;
1287
  }
1288

  
1289
  sk_insert(t);
1290
  sk_alloc_bufs(t);
1291
  s->rx_hook(t, 0);
1292
  return 1;
1185 1293
}
1186 1294

  
1187 1295
/**
......
1197 1305
int
1198 1306
sk_open(sock *s)
1199 1307
{
1200
  int fd;
1201
  int one = 1;
1308
  int af = BIRD_AF;
1309
  int fd = -1;
1202 1310
  int do_bind = 0;
1203 1311
  int bind_port = 0;
1204 1312
  ip_addr bind_addr = IPA_NONE;
1205 1313
  sockaddr sa;
1206
  char *err;
1207 1314

  
1208 1315
  switch (s->type)
1209
    {
1210
    case SK_TCP_ACTIVE:
1211
      s->ttx = "";			/* Force s->ttx != s->tpos */
1212
      /* Fall thru */
1213
    case SK_TCP_PASSIVE:
1214
      fd = socket(BIRD_PF, SOCK_STREAM, IPPROTO_TCP);
1215
      bind_port = s->sport;
1216
      bind_addr = s->saddr;
1217
      do_bind = bind_port || ipa_nonzero(bind_addr);
1218
      break;
1219

  
1220
    case SK_UDP:
1221
      fd = socket(BIRD_PF, SOCK_DGRAM, IPPROTO_UDP);
1222
      bind_port = s->sport;
1223
      bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
1224
      do_bind = 1;
1225
      break;
1226

  
1227
    case SK_IP:
1228
      fd = socket(BIRD_PF, SOCK_RAW, s->dport);
1229
      bind_port = 0;
1230
      bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
1231
      do_bind = ipa_nonzero(bind_addr);
1232
      break;
1233

  
1234
    case SK_MAGIC:
1235
      fd = s->fd;
1236
      break;
1237

  
1238
    default:
1239
      bug("sk_open() called for invalid sock type %d", s->type);
1240
    }
1316
  {
1317
  case SK_TCP_ACTIVE:
1318
    s->ttx = "";			/* Force s->ttx != s->tpos */
1319
    /* Fall thru */
1320
  case SK_TCP_PASSIVE:
1321
    fd = socket(af, SOCK_STREAM, IPPROTO_TCP);
1322
    bind_port = s->sport;
1323
    bind_addr = s->saddr;
1324
    do_bind = bind_port || ipa_nonzero(bind_addr);
1325
    break;
1326
  
1327
  case SK_UDP:
1328
    fd = socket(af, SOCK_DGRAM, IPPROTO_UDP);
1329
    bind_port = s->sport;
1330
    bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
1331
    do_bind = 1;
1332
    break;
1333

  
1334
  case SK_IP:
1335
    fd = socket(af, SOCK_RAW, s->dport);
1336
    bind_port = 0;
1337
    bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
1338
    do_bind = ipa_nonzero(bind_addr);
1339
    break;
1340

  
1341
  case SK_MAGIC:
1342
    af = 0;
1343
    fd = s->fd;
1344
    break;
1345

  
1346
  default:
1347
    bug("sk_open() called for invalid sock type %d", s->type);
1348
  }
1349

  
1241 1350
  if (fd < 0)
1242
    die("sk_open: socket: %m");
1351
    ERR("socket");
1352

  
1353
  s->af = af;
1243 1354
  s->fd = fd;
1244 1355

  
1245
  if (err = sk_setup(s))
1246
    goto bad;
1356
  if (sk_setup(s) < 0)
1357
    goto err;
1247 1358

  
1248 1359
  if (do_bind)
1360
  {
1361
    if (bind_port)
1249 1362
    {
1250
      if (bind_port)
1251
	{
1252
	  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
1253
	    ERR("SO_REUSEADDR");
1363
      int y = 1;
1364

  
1365
      if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(y)) < 0)
1366
	ERR2("SO_REUSEADDR");
1254 1367

  
1255 1368
#ifdef CONFIG_NO_IFACE_BIND
1256
	  /* Workaround missing ability to bind to an iface */
1257
	  if ((s->type == SK_UDP) && s->iface && ipa_zero(bind_addr))
1258
	  {
1259
	    if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
1260
	      ERR("SO_REUSEPORT");
1261
	  }
1369
      /* Workaround missing ability to bind to an iface */
1370
      if ((s->type == SK_UDP) && s->iface && ipa_zero(bind_addr))
1371
      {
1372
	if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &y, sizeof(y)) < 0)
1373
	  ERR2("SO_REUSEPORT");
1374
      }
1262 1375
#endif
1263
	}
1264

  
1265
      fill_in_sockaddr(&sa, bind_addr, s->iface, bind_port);
1266
      if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
1267
	ERR("bind");
1268 1376
    }
1269 1377

  
1270
  fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
1378
    sockaddr_fill(&sa, af, bind_addr, s->iface, bind_port);
1379
    if (bind(fd, &sa.sa, SA_LEN(sa)) < 0)
1380
      ERR2("bind");
1381
  }
1271 1382

  
1272 1383
  if (s->password)
1273
    {
1274
      int rv = sk_set_md5_auth_int(s, &sa, s->password);
1275
      if (rv < 0)
1276
	goto bad_no_log;
1277
    }
1384
    if (sk_set_md5_auth(s, s->daddr, s->iface, s->password) < 0)
1385
      goto err;
1278 1386

  
1279 1387
  switch (s->type)
1280
    {
1281
    case SK_TCP_ACTIVE:
1282
      if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
1283
	sk_tcp_connected(s);
1284
      else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS &&
1285
	       errno != ECONNREFUSED && errno != EHOSTUNREACH && errno != ENETUNREACH)
1286
	ERR("connect");
1287
      break;
1288
    case SK_TCP_PASSIVE:
1289
      if (listen(fd, 8))
1290
	ERR("listen");
1291
      break;
1292
    case SK_MAGIC:
1293
      break;
1294
    default:
1295
      sk_alloc_bufs(s);
1296
#ifdef IPV6
1297
#ifdef IPV6_MTU_DISCOVER
1298
      {
1299
	int dont = IPV6_PMTUDISC_DONT;
1300
	if (setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
1301
	  ERR("IPV6_MTU_DISCOVER");
1302
      }
1303
#endif
1304
#else
1305
#ifdef IP_PMTUDISC
1306
      {
1307
	int dont = IP_PMTUDISC_DONT;
1308
	if (setsockopt(fd, SOL_IP, IP_PMTUDISC, &dont, sizeof(dont)) < 0)
1309
	  ERR("IP_PMTUDISC");
1310
      }
1311
#endif
1312
#endif
1313
    }
1388
  {
1389
  case SK_TCP_ACTIVE:
1390
    sockaddr_fill(&sa, af, s->daddr, s->iface, s->dport);
1391
    if (connect(fd, &sa.sa, SA_LEN(sa)) >= 0)
1392
      sk_tcp_connected(s);
1393
    else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS &&
1394
	     errno != ECONNREFUSED && errno != EHOSTUNREACH && errno != ENETUNREACH)
1395
      ERR2("connect");
1396
    break;
1397

  
1398
  case SK_TCP_PASSIVE:
1399
    if (listen(fd, 8) < 0)
1400
      ERR2("listen");
1401
    break;
1402

  
1403
  case SK_MAGIC:
1404
    break;
1405

  
1406
  default:
1407
    sk_alloc_bufs(s);
1408
  }
1314 1409

  
1315 1410
  if (!(s->flags & SKF_THREAD))
1316 1411
    sk_insert(s);
1317 1412
  return 0;
1318 1413

  
1319
bad:
1320
  log(L_ERR "sk_open: %s: %m", err);
1321
bad_no_log:
1414
err:
1322 1415
  close(fd);
1323 1416
  s->fd = -1;
1324 1417
  return -1;
1325 1418
}
1326 1419

  
1327
void
1420
int
1328 1421
sk_open_unix(sock *s, char *name)
1329 1422
{
1330
  int fd;
1331 1423
  struct sockaddr_un sa;
1332
  char *err;
1424
  int fd;
1425

  
1426
  /* We are sloppy during error (leak fd and not set s->err), but we die anyway */
1333 1427

  
1334 1428
  fd = socket(AF_UNIX, SOCK_STREAM, 0);
1335 1429
  if (fd < 0)
1336
    ERR("socket");
1337
  s->fd = fd;
1338
  if (err = sk_setup(s))
1339
    goto bad;
1340
  unlink(name);
1430
    return -1;
1431

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff