Free everything before exiting
[mspang/pyceo.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 void free_fqdn(void) {
30     strbuf_release(&fqdn);
31 }
32
33 static size_t recv_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg, int *notification) {
34     size_t len = 0;
35     int flags;
36     int bytes;
37
38     strbuf_reset(msg);
39
40     do {
41         msg_meta->fromlen = sizeof(msg_meta->from);
42
43         bytes = sctp_recvmsg(sock, msg->buf + len, strbuf_avail(msg) - len,
44                              (sa *)&msg_meta->from, &msg_meta->fromlen, &msg_meta->sinfo, &flags);
45
46         if (bytes < 0)
47             fatalpe("sctp_recvmsg");
48         if (!bytes)
49             break;
50         len += bytes;
51
52         if (msg->len > MAX_MSGLEN)
53             fatal("oversized message received");
54         if (strbuf_avail(msg) < MSG_BUFINC)
55             strbuf_grow(msg, MSG_BUFINC);
56
57     } while (~flags & MSG_EOR);
58
59     if (!bytes && len)
60         fatalpe("EOF in the middle of a message");
61
62     *notification = flags & MSG_NOTIFICATION;
63     if (*notification)
64         notification_dbg(msg->buf);
65
66     strbuf_setlen(msg, len);
67     return len;
68 }
69
70 int receive_one_message(int sock, struct sctp_meta *msg_meta, struct strbuf *msg) {
71     int notification = 0;
72
73     do {
74         recv_one_message(sock, msg_meta, msg, &notification);
75     } while (notification);
76
77     return msg->len > 0;
78 }
79
80 void notification_dbg(char *notification) {
81     union sctp_notification *sn = (union sctp_notification *) notification;
82     char *extra;
83
84     switch (sn->sn_header.sn_type) {
85         case SCTP_ASSOC_CHANGE:
86             extra = "unknown state";
87             switch (sn->sn_assoc_change.sac_state) {
88                 case SCTP_COMM_UP: extra = "established"; break;
89                 case SCTP_COMM_LOST: extra = "lost"; break;
90                 case SCTP_RESTART: extra = "restarted"; break;
91                 case SCTP_SHUTDOWN_COMP: extra = "completed shutdown"; break;
92                 case SCTP_CANT_STR_ASSOC: extra = "cannot start"; break;
93             }
94             debug("association changed: association 0x%x %s", sn->sn_assoc_change.sac_assoc_id, extra);
95             break;
96         case SCTP_PEER_ADDR_CHANGE:
97             extra = "unknown state";
98             switch (sn->sn_paddr_change.spc_state) {
99                 case SCTP_ADDR_AVAILABLE: extra = "unavailable"; break;
100                 case SCTP_ADDR_UNREACHABLE: extra = "unreachable"; break;
101                 case SCTP_ADDR_REMOVED: extra = "removed"; break;
102                 case SCTP_ADDR_ADDED: extra = "added"; break;
103                 case SCTP_ADDR_MADE_PRIM: extra = "made primary"; break;
104 #ifdef SCTP_ADDR_CONFIRMED
105                 case SCTP_ADDR_CONFIRMED: extra = "confirmed"; break;
106 #endif
107             }
108
109             struct sockaddr_in *sa = (struct sockaddr_in *) &sn->sn_paddr_change.spc_aaddr;
110             char addr[INET_ADDRSTRLEN];
111             inet_ntop(AF_INET, &sa->sin_addr, addr, sizeof(addr));
112             debug("peer address change: remote address %s %s", addr, extra);
113             break;
114         case SCTP_REMOTE_ERROR:
115             debug("remote error: association=0x%x error=0x%x",
116                     sn->sn_remote_error.sre_assoc_id,
117                     sn->sn_remote_error.sre_error);
118             break;
119         case SCTP_SEND_FAILED:
120             debug("send failed: association=0x%x error=0x%x",
121                     sn->sn_send_failed.ssf_assoc_id,
122                     sn->sn_send_failed.ssf_error);
123             break;
124         case SCTP_ADAPTATION_INDICATION:
125             debug("adaptation indication: 0x%x",
126                     sn->sn_adaptation_event.sai_adaptation_ind);
127             break;
128         case SCTP_PARTIAL_DELIVERY_EVENT:
129             extra = "unknown indication";
130             switch (sn->sn_pdapi_event.pdapi_indication) {
131                 case SCTP_PARTIAL_DELIVERY_ABORTED:
132                     extra = "partial delivery aborted";
133                     break;
134             }
135             debug("partial delivery event: %s", extra);
136             break;
137         case SCTP_SHUTDOWN_EVENT:
138             debug("association 0x%x was shut down",
139                     sn->sn_shutdown_event.sse_assoc_id);
140             break;
141         default:
142             debug("unknown sctp notification type 0x%x\n",
143                     sn->sn_header.sn_type);
144     }
145 }