1/*
2 * $Id: mnc_opts.c,v 1.3 2004/09/22 16:02:26 colmmacc Exp $
3 *
4 * mnc_opts.c -- Multicast NetCat
5 *
6 * Colm MacCarthaigh, <colm@apache.org>
7 *
8 * Copyright (c) 2007, Colm MacCarthaigh.
9 * Copyright (c) 2004 - 2006, HEAnet Ltd.
10 *
11 * This software is an open source.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * Redistributions of source code must retain the above copyright notice,
18 * this list of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright notice,
21 * this list of conditions and the following disclaimer in the documentation
22 * and/or other materials provided with the distribution.
23 *
24 * Neither the name of the HEAnet Ltd. nor the names of its contributors may
25 * be used to endorse or promote products derived from this software without
26 * specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
32 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 */
41
42#include <stdlib.h>
43#include <stdio.h>
44#include <string.h>
45
46#ifndef WINDOWS
47
48/* UNIX-y includes */
49#include <sys/types.h>
50#include <sys/socket.h>
51#include <netdb.h>
52#else
53
54/* WINDOWS-y includes */
55#include <winsock2.h>
56#include <ws2tcpip.h>
57#endif
58
59#include "mnc.h"
60
61/* Display a usage statement */
62void usage(void)
63{
64	fprintf(stderr,
65		"Usage: mnc [-l] [-i interface] [-p port] group-id "
66		"[source-address]\n\n"
67		"-l :    listen mode\n"
68		"-i :    specify interface to listen\n"
69		"-p :    specify port to listen/send on\n\n");
70	exit(1);
71}
72
73struct mnc_configuration * parse_arguments(int argc, char **argv)
74{
75	/* Utility variables */
76	int					optind,
77						errorcode;
78	struct	addrinfo			hints;
79
80	/* Our persisting configuration */
81	static	struct mnc_configuration	config;
82
83	/* Set some defaults */
84	config.mode	= SENDER;
85	config.port 	= MNC_DEFAULT_PORT;
86	config.iface	= NULL;
87	config.source	= NULL;
88
89	/* Loop through the arguments */
90	for (optind = 1; optind < (argc - 1); optind++)
91	{
92		if ( (argv[optind][0] == '-') || (argv[optind][0] == '/') )
93		{
94			switch(argv[optind][1])
95			{
96				/* Set listening mode */
97				case 'l':	config.mode = LISTENER;
98						break;
99
100				/* Set port */
101				case 'p':	config.port = argv[++optind];
102						break;
103
104				/* Set an interface */
105				case 'i':	config.iface = argv[++optind];
106						break;
107
108				/* Unrecognised option */
109				default:	usage();
110						break;
111			}
112		}
113		else
114		{
115			/* assume we've ran out of options */
116			break;
117		}
118	}
119
120	/* There's a chance we were passed one option */
121	if (optind >= argc || argv[optind][0] == '-')
122	{
123		usage();
124	}
125
126	/* Now make sure we have either exactly 1 or 2 more arguments */
127	if ( (argc - optind) != 1 && (argc - optind) != 2 )
128	{
129		/* We have not been given the right ammount of
130		   arguments */
131		usage();
132	}
133
134	/* You can't have an interface without also listening */
135	if (config.mode == SENDER && config.iface != NULL)
136	{
137		mnc_error("You may only specify the interface when in"
138				" listening mode\n");
139	}
140
141	/* Set some hints for getaddrinfo */
142	memset(&hints, 0, sizeof(hints));
143
144	/* We want a UDP socket */
145	hints.ai_socktype = SOCK_DGRAM;
146
147	/* Don't do any name-lookups */
148	hints.ai_flags = AI_NUMERICHOST;
149
150	/* Get the group-id information */
151	if ( (errorcode =
152	      getaddrinfo(argv[optind], config.port, &hints, &config.group)) != 0)
153	{
154		mnc_error("Error getting group-id address information: %s\n",
155			  gai_strerror(errorcode));
156	}
157
158	/* Move on to next argument */
159	optind++;
160
161	/* Get the source information */
162	if ( (argc - optind) == 1)
163	{
164
165		if ( (errorcode =
166        	      getaddrinfo(argv[optind], config.port, &hints, &config.source))
167		    != 0)
168		{
169			mnc_error("Error getting source-address information: %s\n",
170			          gai_strerror(errorcode));
171		}
172
173		/* Confirm that the source and group are in the same Address Family */
174		if ( config.source->ai_family != config.group->ai_family )
175		{
176			mnc_error("Group ID and Source address are not of "
177				  "the same type\n");
178		}
179	}
180
181	return &config;
182}
183