1/***********************************************************************
2*
3* network.c
4*
5* Code for handling the UDP socket we send/receive on.  All of our
6* tunnels use a single UDP socket which stays open for the life of
7* the application.
8*
9* Copyright (C) 2002 by Roaring Penguin Software Inc.
10*
11* This software may be distributed under the terms of the GNU General
12* Public License, Version 2, or (at your option) any later version.
13*
14* LIC: GPL
15*
16***********************************************************************/
17
18static char const RCSID[] =
19"$Id: network.c,v 1.1.1.1 2008/10/15 03:31:00 james26_jang Exp $";
20
21#include "l2tp.h"
22#include "event.h"
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <errno.h>
26#include <fcntl.h>
27#include <string.h>
28#include <signal.h>
29#include <stdio.h>
30
31/* Our socket */
32int Sock = -1;
33
34static EventHandler *NetworkReadHandler = NULL;
35static void network_readable(EventSelector *es,
36			     int fd,
37			     unsigned int flags,
38			     void *data);
39char Hostname[MAX_HOSTNAME];
40
41static void
42sigint_handler(int sig)
43{
44    static int count = 0;
45
46    count++;
47    fprintf(stderr, "In sigint handler: %d\n", count);
48    if (count < 5) {
49	l2tp_cleanup();
50    }
51    exit(1);
52}
53
54/**********************************************************************
55* %FUNCTION: network_init
56* %ARGUMENTS:
57*  es -- an event selector
58* %RETURNS:
59*  >= 0 if all is OK, <0 if not
60* %DESCRIPTION:
61*  Initializes network; opens socket on UDP port 1701; sets up
62*  event handler for incoming packets.
63***********************************************************************/
64int
65l2tp_network_init(EventSelector *es)
66{
67    struct sockaddr_in me;
68    int flags;
69
70    gethostname(Hostname, sizeof(Hostname));
71    Hostname[sizeof(Hostname)-1] = 0;
72
73    Event_HandleSignal(es, SIGINT, sigint_handler);
74    if (Sock >= 0) {
75	if (NetworkReadHandler) {
76	    Event_DelHandler(es, NetworkReadHandler);
77	    NetworkReadHandler = NULL;
78	}
79	close(Sock);
80	Sock = -1;
81    }
82    Sock = socket(PF_INET, SOCK_DGRAM, 0);
83    if (Sock < 0) {
84	l2tp_set_errmsg("network_init: socket: %s", strerror(errno));
85	return -1;
86    }
87
88    me.sin_family = AF_INET;
89    me.sin_addr = Settings.listen_addr;
90    me.sin_port = htons((uint16_t) Settings.listen_port);
91    if (bind(Sock, (struct sockaddr *) &me, sizeof(me)) < 0) {
92	l2tp_set_errmsg("network_init: bind: %s", strerror(errno));
93	close(Sock);
94	Sock = -1;
95	return -1;
96    }
97
98    /* Set socket non-blocking */
99    flags = fcntl(Sock, F_GETFL);
100    flags |= O_NONBLOCK;
101    fcntl(Sock, F_SETFL, flags);
102
103    /* Set up the network read handler */
104    Event_AddHandler(es, Sock, EVENT_FLAG_READABLE,
105		     network_readable, NULL);
106    return Sock;
107}
108
109/**********************************************************************
110* %FUNCTION: network_readable
111* %ARGUMENTS:
112*  es -- event selector
113*  fd -- socket
114*  flags -- event-handling flags telling what happened
115*  data -- not used
116* %RETURNS:
117*  Nothing
118* %DESCRIPTION:
119*  Called when a packet arrives on the UDP socket.
120***********************************************************************/
121static void
122network_readable(EventSelector *es,
123		 int fd,
124		 unsigned int flags,
125		 void *data)
126{
127    l2tp_dgram *dgram;
128
129    struct sockaddr_in from;
130    dgram = l2tp_dgram_take_from_wire(&from);
131    if (!dgram) return;
132
133    /* It's a control packet if we get here */
134    l2tp_tunnel_handle_received_control_datagram(dgram, es, &from);
135    l2tp_dgram_free(dgram);
136}
137