/*
 * Copyright (c) 2000 Columbia University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by Columbia University
 * and its contributors.'' Neither the name of the University nor the names 
 * of its contributors may be used to endorse or promote products derived 
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Written by Ping Pan, Columbia University/Bell Labs, 2000
 *
 * The author would like to thank Bell Labs for providing time and freedom
 * to complete this work. Please forward bug fixes, enhancements and questions
 * to pingpan@cs.columbia.edu.
 */

#ifndef _YES_VAR_H_
#define _YES_VAR_H_

/* The default place to pick of the pid and log file 
 */

#define YES_PID	"/var/tmp/yes.pid"
#define YES_LOG	"/var/tmp/yes.log"


/* Since YESSIR is responsible for relaying messages between interfaces,
 * it'll be stupid to have more than one daemon running at any given time.
 * We thus force to have one daemon per system. We use a dummy fixed 
 * socket number to check the daemon in yes_alive().
 */

#define YES_LOCK_PORT	0xBEEF


/* By default, yessir daemon gets ingress interface index and 
 * the local flag from ther kernel.
 */

#define YES_MAXCTRLSIZE						\
	(sizeof(struct cmsghdr) + sizeof(struct sockaddr_dl) +  \
	sizeof(struct cmsghdr) + sizeof(int))

#define CMSG_IFINDEX(cmsg)				\
	(((struct sockaddr_dl*)(cmsg + 1))->sdl_index)  \

#define CMSG_LOCAL(cmsg)	(*(int *)(cmsg + 1))


/* Allocate enough space to hold the max size RTCP messages that
 * the link layer would allow.
 */

#define YES_MAXPKTSIZE	9600


/* The space for route query 
 */

#define YES_RTBUFLEN	(sizeof(struct rt_msghdr) + 512)


/* interface def's 
 */

#ifdef sgi

#define IFF_UP_RUNNING (IFF_RUNNING | IFF_UP)
#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) \
                    : sizeof(__uint64_t))

#else

#define IFF_UP_RUNNING IFF_UP
#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
                    : sizeof(long))

#endif

#define S_ADDR(x) (((struct sockaddr_in *)(x))->sin_addr.s_addr) 
#define iff_alive(f) (((f) & IFF_UP_RUNNING) == IFF_UP_RUNNING) 


#define bad_addr(x)						\
	(((ntohl(x) >> 24) == 0 || (ntohl(x) >> 24) == 0xff) ? 1 : 0)


/* functions */

/* yessir.c */
void	yessir_read(u_char *, int, int, int);
int	rtcp_map(struct rtcphdr *rpkt, int lgt);
void	yessir_valid(yessirErr *);
void	yessir_input(char *, int, int, int, struct in_addr *);
int	yessir_mb_input(yesOutEntry *, RIF *);
int	yessir_is_input(yesOutEntry *, RIF *, yessirErr *);
int	yessir_ds_input(yesOutEntry *, RIF *, yessirErr *);
void	yes_retry();
int	yes_retry_resv(yesPendingEntry *);
int	yessir_mb_resv(yesEntry *, yesOutEntry *, RIF *);
int	yessir_is_resv(yesEntry *, yesOutEntry *, RIF *, yessirErr *);
int	yessir_ds_resv(yesEntry *, yesOutEntry *, RIF *, yessirErr *);

void	yes_rmresv(yesEntry *, yesOutEntry *);
void	yes_send_error(char *, int, struct in_addr *, yessirErr *);
void	yes_send_chksum(char *, int, struct in_addr *);

int	yes_timerinit();
void	yesrefresh();
void	yesrefresh_slot(int slot_num);

/* table.c */
int	yes_tabinit();
int	yestab_refill();
int	yes_refill_ftab(int num);
int	yes_refill_otab(int num);
int	yes_refill_ttab(int num);
int	yes_refill_ptab(int num);
int	yestab_deplete();
int	yes_deplete_ftab(int num);
int	yes_deplete_otab(int num);
int	yes_deplete_ttab(int num);
int	yes_deplete_ptab(int num);

yesEntry *yesget(struct in_addr *, u_int32_t, struct in_addr *, u_int32_t);
yesEntry *yesadd(struct in_addr *, u_int32_t, struct in_addr *, u_int32_t);
int	yesdel(struct in_addr *, u_int32_t, struct in_addr *, u_int32_t);
int	yesfree(yesEntry *);
yesOutEntry *yesadd_egress(yesEntry *ye);
int	yesdel_egress(yesEntry *);
int	yesdel_timer(yesEntry *);
void	yesenq_resv(yesEntry *);
void	yesdel_pending(yesEntry *);

RIF	*rif_add(u_int16_t);
RIF	*rif_get(u_int16_t);
int	rif_del(RIF *);
void	rif_cleanup(RIF *);
int	rif_refill();
int	rif_deplete();


/* main.c */
int	yes_savepid(int);
void	sigpipe(int);
void	sigint(int);
void	sigterm(int);
void	nosir();
int	yes_alive();
void	yes_usage();
int	sockinit();
void	sockreset();
void	yes_sockread(int);
void	yes_send(char *, int, struct in_addr *);
void	stat_sockread(int);
void	stat_send(char *, int, struct sockaddr *);
int	yes_rtquery(struct in_addr *);

void	rif_up(RIF *, struct if_msghdr *);
void	rif_down(RIF *);
void	rif_change(RIF *, struct ifa_msghdr *);
int	rif_check();
int	its_for_me(struct in_addr *);

/* parms.c */
void	yestat_read(u_char *, struct sockaddr *);

/* yestc.c */
extern u_int32_t	(*TC_Add_Filter)();
extern void		(*TC_Del_Filter)();
extern u_int32_t	(*TC_Make_Resv)();
extern int		(*TC_Modify_Resv)();
extern void		(*TC_Del_Resv)();
extern u_int32_t	(*TC_Make_IntServ_Resv)();
extern int		(*TC_Modify_IntServ_Resv)();
extern int		(*TC_Admit_IntServ)();
int			yes_tcinit();

/* util.c */
extern FILE *ftrace;
extern char inittracename[MAXPATHLEN+1];

void set_tracefile(char *, char *, int);
char *ts(time_t secs);
void msglog(char *p, ...);
void logbad(int dump, char *p, ...);
void lastlog();
void tmsg(char *p, ...);
void trace_close(void);
void trace_flush(void);
void trace_off(char *p, ...);
void timevalsub(struct timeval *, struct timeval *, struct timeval *);

#endif
