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