825c9176ede60f1e5c55fc887d66a537ed2dc861
[public/pyceo-broken.git] / src / net.c
1 #include <stdio.h>
2 #include <sys/utsname.h>
3 #include <unistd.h>
4 #include <netdb.h>
5
6 #include "util.h"
7 #include "net.h"
8 #include "gss.h"
9 #include "strbuf.h"
10
11 struct strbuf fqdn = STRBUF_INIT;
12
13 const size_t MAX_MSGLEN = 65536;
14 const size_t MSG_BUFINC = 4096;
15
16 void setup_fqdn(void) {
17     struct utsname uts;
18     struct hostent *lo;
19
20     if (uname(&uts))
21         fatalpe("uname");
22     lo = gethostbyname(uts.nodename);
23     if (!lo)
24         fatalpe("gethostbyname");
25
26     strbuf_addstr(&fqdn, lo->h_name);
27 }
28
29 static size_t recv_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg, int *notification) {
30     size_t len = 0;
31     int flags;
32     int bytes;
33
34     strbuf_reset(msg);
35
36     do {
37         msg_meta->fromlen = sizeof(msg_meta->from);
38
39         bytes = sctp_recvmsg(sock, msg->buf + len, strbuf_avail(msg) - len,
40                              (sa *)&msg_meta->from, &msg_meta->fromlen, &msg_meta->sinfo, &flags);
41
42         if (bytes < 0)
43             fatalpe("sctp_recvmsg");
44         if (!bytes)
45             break;
46         len += bytes;
47
48         if (msg->len > MAX_MSGLEN)
49             fatal("oversized message received");
50         if (strbuf_avail(msg) < MSG_BUFINC)
51             strbuf_grow(msg, MSG_BUFINC);
52
53     } while (~flags & MSG_EOR);
54
55     if (!bytes && len)
56         fatalpe("EOF in the middle of a message");
57
58     *notification = flags & MSG_NOTIFICATION;
59     if (*notification)
60         notification_dbg(msg->buf);
61
62     strbuf_setlen(msg, len);
63     return len;
64 }
65
66 int receive_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg) {
67     int notification = 0;
68
69     do {
70         recv_one_message(sock, msg_meta, msg, &notification);
71     } while (notification);
72
73     return msg->len > 0;
74 }
75
76 void notification_dbg(char *notification) {
77     union sctp_notification *sn = (union sctp_notification *) notification;
78     char *extra;
79
80     switch (sn->sn_header.sn_type) {
81         case SCTP_ASSOC_CHANGE:
82             extra = "unknown state";
83             switch (sn->sn_assoc_change.sac_state) {
84                 case SCTP_COMM_UP: extra = "established"; break;
85                 case SCTP_COMM_LOST: extra = "lost"; break;
86                 case SCTP_RESTART: extra = "restarted"; break;
87                 case SCTP_SHUTDOWN_COMP: extra = "completed shutdown"; break;
88                 case SCTP_CANT_STR_ASSOC: extra = "cannot start"; break;
89             }
90             debug("association changed: association 0x%x %s", sn->sn_assoc_change.sac_assoc_id, extra);
91             break;
92         case SCTP_PEER_ADDR_CHANGE:
93             extra = "unknown state";
94             switch (sn->sn_paddr_change.spc_state) {
95                 case SCTP_ADDR_AVAILABLE: extra = "unavailable"; break;
96                 case SCTP_ADDR_UNREACHABLE: extra = "unreachable"; break;
97                 case SCTP_ADDR_REMOVED: extra = "removed"; break;
98                 case SCTP_ADDR_ADDED: extra = "added"; break;
99                 case SCTP_ADDR_MADE_PRIM: extra = "made primary"; break;
100 #ifdef SCTP_ADDR_CONFIRMED
101                 case SCTP_ADDR_CONFIRMED: extra = "confirmed"; break;
102 #endif
103             }
104
105             struct sockaddr_in *sa = (struct sockaddr_in *) &sn->sn_paddr_change.spc_aaddr;
106             char addr[INET_ADDRSTRLEN];
107             inet_ntop(AF_INET, &sa->sin_addr, addr, sizeof(addr));
108             debug("peer address change: remote address %s %s", addr, extra);
109             break;
110         case SCTP_REMOTE_ERROR:
111             debug("remote error: association=0x%x error=0x%x",
112                     sn->sn_remote_error.sre_assoc_id,
113                     sn->sn_remote_error.sre_error);
114             break;
115         case SCTP_SEND_FAILED:
116             debug("send failed: association=0x%x error=0x%x",
117                     sn->sn_send_failed.ssf_assoc_id,
118                     sn->sn_send_failed.ssf_error);
119             break;
120         case SCTP_ADAPTATION_INDICATION:
121             debug("adaptation indication: 0x%x",
122                     sn->sn_adaptation_event.sai_adaptation_ind);
123             break;
124         case SCTP_PARTIAL_DELIVERY_EVENT:
125             extra = "unknown indication";
126             switch (sn->sn_pdapi_event.pdapi_indication) {
127                 case SCTP_PARTIAL_DELIVERY_ABORTED:
128                     extra = "partial delivery aborted";
129                     break;
130             }
131             debug("partial delivery event: %s", extra);
132             break;
133         case SCTP_SHUTDOWN_EVENT:
134             debug("association 0x%x was shut down",
135                     sn->sn_shutdown_event.sse_assoc_id);
136             break;
137         default:
138             debug("unknown sctp notification type 0x%x\n",
139                     sn->sn_header.sn_type);
140     }
141 }