652c4957d9460b0e4b9ed9e0a95710c75925b24c
[radsecproxy.git] / lib / packet.c
1 #include <string.h>
2 #include <assert.h>
3 #include <freeradius/libradius.h>
4 #include <event2/event.h>
5 #include <event2/bufferevent.h>
6 #include "libradsec.h"
7 #include "libradsec-impl.h"
8 #if defined DEBUG
9 #include "debug.h"
10 #endif
11
12 int
13 _packet_create (struct rs_connection *conn, struct rs_packet **pkt_out,
14                 int code)
15 {
16   struct rs_packet *p;
17   RADIUS_PACKET *rpkt;
18
19   *pkt_out = NULL;
20
21   rpkt = rad_alloc (1);
22   if (!rpkt)
23     return rs_conn_err_push (conn, RSE_NOMEM, __func__);
24   rpkt->id = -1;
25   rpkt->code = code;
26
27   p = (struct rs_packet *) malloc (sizeof (struct rs_packet));
28   if (!p)
29     {
30       rad_free (&rpkt);
31       return rs_conn_err_push (conn, RSE_NOMEM, __func__);
32     }
33   memset (p, 0, sizeof (struct rs_packet));
34   p->conn = conn;
35   p->rpkt = rpkt;
36
37   *pkt_out = p;
38   return RSE_OK;
39 }
40
41 int
42 rs_packet_create_acc_request (struct rs_connection *conn,
43                               struct rs_packet **pkt_out,
44                               const char *user_name, const char *user_pw)
45 {
46   struct rs_packet *pkt;
47   struct rs_attr *attr;
48
49   if (_packet_create (conn, pkt_out, PW_AUTHENTICATION_REQUEST))
50     return -1;
51   pkt = *pkt_out;
52
53   if (rs_attr_create (conn, &attr, "User-Name", user_name))
54     return -1;
55   rs_packet_add_attr (pkt, attr);
56
57   if (rs_attr_create (conn, &attr, "User-Password", user_pw))
58     return -1;
59   /* FIXME: need this too? rad_pwencode(user_pw, &pwlen, SECRET, reqauth) */
60   rs_packet_add_attr (pkt, attr);
61
62   return RSE_OK;
63 }
64
65 static void
66 _event_cb (struct bufferevent *bev, short events, void *ctx)
67 {
68   struct rs_packet *pkt = (struct rs_packet *) ctx;
69
70   assert (pkt);
71   assert (pkt->conn);
72   if (events & BEV_EVENT_CONNECTED)
73     {
74 #if defined (DEBUG)
75       fprintf (stderr, "%s: connected\n", __func__);
76 #endif
77       rad_encode (pkt->rpkt, NULL, pkt->conn->active_peer->secret);
78 #if defined (DEBUG)
79       fprintf (stderr, "%s: about to send this to %s:\n", __func__, "<fixme>");
80       rs_dump_packet (pkt);
81 #endif
82       if (bufferevent_write(bev, pkt->rpkt->data, pkt->rpkt->data_len))
83         rs_conn_err_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
84                              "bufferevent_write");
85       /* Packet will be freed in write callback.  */
86     }
87   else if (events & BEV_EVENT_ERROR)
88     rs_conn_err_push_fl (pkt->conn, RSE_CONNERR, __FILE__, __LINE__, NULL);
89 }
90
91 void
92 rs_packet_destroy(struct rs_packet *pkt)
93 {
94   rad_free (&pkt->rpkt);
95   rs_free (pkt->conn->ctx, pkt);
96 }
97
98 static void
99 _write_cb (struct bufferevent *bev, void *ctx)
100 {
101   struct rs_packet *pkt = (struct rs_packet *) ctx;
102
103   assert (pkt);
104   assert (pkt->conn);
105 #if defined (DEBUG)
106   fprintf (stderr, "%s: packet written, breaking event loop\n", __func__);
107 #endif
108   if (event_base_loopbreak (pkt->conn->evb) < 0)
109     abort ();                   /* FIXME */
110   rs_packet_destroy (pkt);
111 }
112
113 int
114 rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data)
115 {
116   struct bufferevent *bev;
117   struct rs_peer *p;
118
119   assert (pkt->rpkt);
120
121   if (rs_conn_open (conn))
122     return -1;
123   p = conn->active_peer;
124   assert (p);
125
126   assert (conn->active_peer->s >= 0);
127   bev = bufferevent_socket_new (conn->evb, conn->active_peer->s, 0);
128   if (!bev)
129     return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
130                                 "bufferevent_socket_new");
131   if (bufferevent_socket_connect (bev, p->addr->ai_addr, p->addr->ai_addrlen) < 0)
132     {
133       bufferevent_free (bev);
134       return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
135                                   "bufferevent_socket_connect");
136     }
137
138   bufferevent_setcb (bev, NULL, _write_cb, _event_cb, pkt);
139   event_base_dispatch (conn->evb);
140 #if defined (DEBUG)
141   fprintf (stderr, "%s: event loop done\n", __func__);
142   assert (event_base_got_break(conn->evb));
143 #endif
144
145   return RSE_OK;
146 }
147
148 int rs_packet_receive(struct rs_connection *conn, struct rs_packet **pkt)
149 {
150   return rs_conn_err_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__,
151                               "%s: NYI", __func__);
152 }
153
154 void
155 rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr)
156 {
157   pairadd (&pkt->rpkt->vps, attr->vp);
158   attr->pkt = pkt;
159 }