//	CN[h
#include	<stdio.h>	// Wwb_̃CN[h
#include	<stdlib.h>	// Wwb_̃CN[h
#include	<string.h>	// Wwb_̃CN[h
#include	<ctype.h>	// Wwb_̃CN[h
#include	<string.h>	// Wwb_̃CN[h
#include	<time.h>	// Wwb_̃CN[h

#ifdef	WIN32	// WindowsȂ
 #include	<winsock2.h>	// \Pbg֘Awb_̃CN[h
#else		// LinuxȂ
 #include	<sys/types.h>	// ^錾wb_̃CN[h
 #include	<sys/socket.h>	// \Pbg֘Awb_̃CN[h
 #include	<netinet/in.h>	// C^[lbg֘Awb_̃CN[h
 #include	<arpa/inet.h>	// C^[lbg֘Awb_̃CN[ĥQ
 #include	<netdb.h>	// C^[lbg֘Awb_̃CN[ĥR
 #define	SOCKET		int	// LinuxłSOCKET^̐錾
 #define	INVALID_SOCKET	-1	// Linuxł̃G[Xe[^X
 #define	SOCKET_ERROR	-1	// Linuxł̃G[Xe[^X
#endif
//	fobOpo
//#define	DebugPrint(x, ...)	fprintf(x, __VA_ARGS__)//fobOL
#define		DebugPrint(x, ...)	// ʏ͂Ȃɂo͂Ȃ

//
//	^錾̃GCAX
//
#define	UINT8	unsigned char	// unsigned char͒̂UINT8ƏΒZ
#define INT8	char		// char͒ẐINT8Ə悤ɂ
#define	UINT16	unsigned short	// unsigned short͒̂UINT16ƏΒZ
#define INT16	short		// short͒ẐINT16Ə悤ɂ
#define UINT32	unsigned long	// unsigned long͒̂UINT32ƏΒZ
#define INT32	long		// long͒ẐINT32Ə悤ɂ

//
//	OIDe[u\
//
typedef struct
{
	UINT8	*name;		// OIDIuWFNg̖Oւ̃|C^
	UINT8	*value;		// lւ̃|C^
	UINT32	namelen;	// O̒
	UINT32	valattr;	// l̑
} OidTable;

//
//	OIDLbV\
//
typedef struct
{		
	UINT32	Id;		// foCXID
	UINT32	life;		// LbVێ(b)
	INT32	Data[4];	// f[^(4ch)
} OidCache_t;

//
//	萔錾
//
#define	OIDBUFSIZE	1024	// OIDLbṼTCY	
#define	OIDTABLECOUNT	5	// `ςOIDIuWFNg̑
#define	IDINDEX		0	// IDOID̊JnCfbNX
#define	DATASTART	1	// f[^OID̊JnCfbNX

//
//	gݍݍςOIDe[u
//
const INT8	*InitOidList[] = {
"1.3.6.1.4.1.37510.0.0.0",	// foCXIDOID 
"1.3.6.1.4.1.37510.0.1",	// f[^(ch1)OID
"1.3.6.1.4.1.37510.0.2",	// f[^(ch2)OID
"1.3.6.1.4.1.37510.0.3",	// f[^(ch3)OID
"1.3.6.1.4.1.37510.0.4"		// f[^(ch4)OID
};

//
//	ϐ錾
//
OidCache_t	*OidCache;	// OIDLbVւ̃|C^
UINT8	*Community;		// R~jeBւ̃|C^
UINT16	SnmpPort;		// SNMP|[gԍ(161)
UINT16	MaxCache;		// őOIDLbV
UINT16	IdNumber;		// foCXID

//
//	WCũGCAX
//
#define	MemoryAlloc	malloc	// m
#define	BufCopy(x,y,z)	memcpy(x,y,z)	// Rs[
#define	MemClear(x,y)	memset(x,0,y)	// NA
#define	StrLen(x)	strlen((INT8*)x)		// strlen
#define	StrCpy(x,y)	strcpy((INT8*)x,(INT8*)y)	// strcpy
#define	StrNcmp(x,y,z)	strncmp((INT8*)x,(INT8*)y,z)	// strncmp

//
//	J
//
void MemoryFree(void *p)
{
	if(p)	// |C^NULLłȂȂ
		free(p);	// J
}

//
//	BERGg̒𓾂
//
UINT32 GetElementLen(UINT8 **p)
{
UINT32	c;
	c = **p;	// tB[h𓾂
	(*p)++;		// |C^ɐi߂
	return c;	// Ԃ
}

//
//	BERGgXLbv
//
void SkipElement(UINT8 **p)
{
UINT32	i;
	(*p)++;		// |C^ɐi߂
	i = GetElementLen(p);	// Gg̒𓾂
	(*p) += i;	// |C^i߂
}

//
//	l𓾂
//
INT32 GetInteger(UINT8 **p)
{
UINT8	 c;
UINT32 i, j;
INT32		r;
	c = **p;	// ^O̒l𓾂
	if(c != 2	// ^OIntegerH
	&& c != 5	// ^ONULLH
	&& c != 0x40	// ^OIP addressH
	&& c != 0x41	// ^OCounterH
	&& c != 0x42	// ^OGuage counterH
	&& c != 0x43)	// ^OTime tick?
	{	// ̂ǂłȂȂ
		SkipElement(p);	// GgXLbv
		return -1;	// G[^[
	}
	(*p)++;		// |C^i߂ 
	j = (UINT8)GetElementLen(p);	// Gg̒𓾂
	for(r = 0, i = 0; i < j; i++)	// ̕JԂ
	{
		r = (r << 8) | **p;	// 1oCgǂ݂ȂoCiώZ
		(*p)++;		// |C^i߂
	}
	return r;	// ʂԂ
}

//
//	񂩂32rbgl𓾂
//
INT32 ParseNum(UINT8 *ptr)
{
INT32	val = 0;	// ʂ\߃NA
	for(;;)		// [v
	{
		if(*ptr < '0' || *ptr > '9')	// ?
			break;	// łȂȂ烋[v𔲂
		val = val * 10 + *ptr++ - '0';	// 10iƂĐώZ
	}
	return val;	// ʂԂ
}

//
//	Gg當𒊏oĕԂ
//
UINT8 *GetString(UINT8 **p)
{
UINT8 c, *r;
UINT32	i, j;
	c = **p;	// ^O𓾂
	if(c != 4)	// String^OH
	{		// łȂȂ
		SkipElement(p);	// GgXLbv
		return NULL;	// G[Ȃ̂NULLԂ
	}
	(*p)++;		// |C^i߂ 
	j = (UINT8)GetElementLen(p);	// Gg̒𓾂
	if(j == 0)	// 0?
		return NULL;	// G[Ȃ̂NULLԂ
	r = (UINT8*)MemoryAlloc(j + 1);	// ̊i[ɕKvȗ̈m
	for(i = 0; i < j; i++)	// 1Rs[郋[v
	{
		r[i] = **p;	// obt@ɕRs[
		(*p)++;		// |C^i߂
	}
	r[i] = '\0';	// EOSZbg
	return r;	// ̃|C^ĕԂ
}

//
//	OID񂩂BERŃGR[hꂽGg𓾂*resɊi[
//
UINT32 ParseOidSub(UINT8 *s, UINT8 *res)
{
UINT32	c;
UINT32	i, j, len;
UINT32	n;
	len = 0;	//@NAĂ
	if(*s == '.')	// ŏ̓sIhȂ
		s++;	// ŏ̃sIh̓XLbv
	for(i = 0;;i++)	// XL郋[v
	{
		c = *s;	// 𓾂
		if(c == '\0' || c == '@')	// OID̏I肩H
			return len;	// IuWFNg̒ĕԂ
		n = 0;	// lNA
		for(;;)	// oCiɕϊ
		{
			c = *s++;	// 𓾂
			if(isdigit(c))	// ?
				n = n * 10 + c - '0';	// Ȃ10iŐώZ
			else if(c == '\0' || c == '@')	// I?
			{
				s--;	// 1߂Ă܂EOSǂ߂悤ɂĂ
				break;	// ϊ[v𔲂 
			}
			else if(c == '.')	// sIhH 
				break;	// ϊ[v𔲂 
			else		// ̔񐔎H
				return 0;	// G[Ȃ̂0ċA
		}
		if(i == 0)	// OIDŏ1H
		{
			j = (UINT8)n;	// Ƃ肠oĂ
			continue;	// ̐͂
		}
		if(i == 1)	// OID2Ԗڂ̐?
		{
			n += j * 40;	// ŏ̐*40{2Ԗڂ̐𓾂 (1.3.Ȃ0x2bɂȂ)
		}
		if(n < 127)	// l127ȉH
		{
			if(res)		// i[obt@w肳Ă
				*res++ = (UINT8)n;	// 1oCgi[
			len++;		// 1₷
		}
		else if(n < 16384)	// 2oCgŎ܂͈͓H
		{			// Ȃ
			if(res)		// i[obt@w肳Ă
			{
				*res++ = (UINT8)((n >> 7) | 0x80);	// MSBZbg1oCgڂi[
				*res++ = (UINT8)(n & 0x7f);		// MSBNA2oCgڂi[
			}
			len += 2;	// 2₷
		}
		else	// 3oCgŐli[
		{
			if(res)		// i[obt@w肳Ă
			{
				*res++ = (UINT8)((n >> 14) | 0x80);	// MSBZbg1oCgڂi[
				*res++ = (UINT8)((n >> 7) | 0x80);	// MSBZbg2oCgڂi[
				*res++ = (UINT8)(n & 0x7f);		// MSBNA3oCgڂi[
			}
			len += 3;	// 3₷
		}
	}
}

//
//	OID񂩂BERGR[hꂽGg𓾂
//	obt@Ɋi[A̒ƃ|C^Ԃ
//
UINT32 ParseOidStr(UINT8 *s, UINT8 **r)
{
UINT32	len;
UINT8		*buf;
	len = ParseOidSub(s, NULL);	// ܂obt@ƂNULLw肵Ē𒲂ׂ
	if(len == 0)			// Ȃ炩̃G[?
		return 0;		// 0ŋA
	buf = (UINT8*)MemoryAlloc(len);	// i[ɕKvȃobt@̈mۂ
	len = ParseOidSub(s, buf);	// obt@w肵čx̓f[^i[
	*r = buf;			// obt@ւ̃|C^Ԃ
	return len;			// ċA
}

//
//	SNMPpPbgɂOIDGgƂɑl𓾂
//	OIDe[uɊi[
//
UINT8 GetOidData(UINT8 **p, OidTable *oidtbl)
{
UINT8		*s;
UINT32	c, i, j;
	s = *p;			// ݂̃|C^ۑĂ
	c = **p;		// ŏ̃^O𓾂
	if(**p != 0x30)		// z^OH
		return 1;	// ႤȂG[ŋA
	(*p)++;			// |C^i߂
	j = (UINT8)GetElementLen(p);	// OIDGg̒𓾂
	if(j == 0)		// 0H
		return 1;	// G[Ȃ̂1ċA
	s += j + 2;		// OIDGgXLbṽ|C^𓾂
	c = **p;		// ܂OIDGg`FbNB^O𓾂
	if(c != 6)		// OID^OH
		return 1;	// OID^OłȂ΃G[Ȃ̂1ċA
	(*p)++;			// |C^i߂ 
	j = (UINT8)GetElementLen(p);	// ɑOIDGg̒𓾂
	if(j == 0)		// ȃGg?
		return 1;	// G[Ȃ̂1ċA
	if(oidtbl)		// ʊi[pOIDe[u͎w肳Ă邩H
	{
		oidtbl->name = (UINT8*)MemoryAlloc(j);	// OIDGgi[obt@̈m
		oidtbl->namelen = j;	// OIDGg̒i[
		for(i = 0; i < j; i++)	// OIDGgRs[郋[v
		{
			oidtbl->name[i] = **p;	// 1oCgRs[Ă
			(*p)++;		// |C^i߂
		}
	}
	else
		(*p) += j;	// i[pobt@w肳ĂȂΓǂݍ݃|C^i߂
	c = **p;		// ɑf[^̃^O𓾂
	if(c == 5)		// NULL^OH
	{
		(*p)++;		// |C^i߂
		j = (UINT8)GetElementLen(p);	// NULLGg̒𓾂(K1̂͂)
		(*p) += j;	// |C^i߂
		if(oidtbl)	// ʊi[pOIDe[u͎w肳Ă邩H
			oidtbl->valattr = 5;	// NULL
	}
	else if(c == 2 		// ^OH
	|| c == 0x40		// IPAhX^O
	|| c == 0x41		// JE^^OH
	|| c == 0x42		// JE^^OH
	|| c == 0x43)		// `bNJE^^OH
	{			// L̂ꂩ(f[^͐l)Ȃ
		(*p)++;		// ǂݍ݃|C^i߂Đlf[^֐i
		j = (UINT8)GetElementLen(p);	// Gg̒𓾂
		if(oidtbl)	// ʊi[pOIDe[u͎w肳Ă邩H
		{		// obt@w肳ĂΎۂɊi[
			oidtbl->valattr = c;	// 
			oidtbl->value = (UINT8*)MemoryAlloc(4);	// ő32rbg̐i[obt@̈m
			*(UINT32*)oidtbl->value = 0;	// ̈NA(4oCg)
			for(i = 0; i < j; i++)	// Gg̒𓾂
			{	// oCgPʂɃoCiώZ
				*(UINT32*)oidtbl->value = (*(UINT32*)oidtbl->value << 8) | **p;	// oCiώZ
				(*p)++;	// |C^i߂
			}
		}
		else 
			(*p) += j;//i[pobt@w肳ĂȂΓǂݍ݃|C^i߂
	}
	else if(c == 4) // ^O?
	{
		(*p)++;		// |C^i߂
		j = (UINT8)GetElementLen(p);	// ̒𓾂
		if(oidtbl)	// ʊi[pOIDe[u͎w肳Ă邩H
		{		// Ȃ當ۂɊi[
			oidtbl->valattr = c;	// 񑮐
			oidtbl->value = (UINT8*)MemoryAlloc(j + 1);	// i[̈m(EOSZ)
			for(i = 0; i < j; i++)	// Rs[郋[v
			{
				oidtbl->value[i] = **p;	// 1Rs[
				(*p)++;			// ̕ɐi
			}
			oidtbl->value[i] = '\0';	// EOS(\0)
		}
		else
			(*p) += j;	//i[pobt@w肳ĂȂΓǂݍ݃|C^i߂
	}
	else
		return 1;	// Ԉ^OȂG[Ȃ̂1ċA
	return (*p != s);	// Ŝ̒`FbNĐOKȂ0G[Ȃ1ċA
}

//
//	obt@̃|C^w肳Ă΃f[^i[
//
void StoreSub(UINT8 *p, UINT32 *index, UINT32 data)
{
	if(p)			// i[̃|C^NULLłȂ
		p[*index] = (UINT8)data;	// f[^i[
	(*index)++;		// i[CfbNXi߂
}

//
//	2oCg̒Ggi[
//
static void StoreLength(UINT8 *p, UINT32 *index, UINT32 data)
{
	StoreSub(p, index, 0x82);	// 0x82(2̐l̃wb_)
	StoreSub(p, index, data >> 8);	// ʃoCgi[
	StoreSub(p, index, data);	// ʃoCgi[
}

//
//	Ggi[
//
void SetString(UINT8 *p, UINT32 *index, UINT8 attr, UINT8 *data, UINT8 size)
{
UINT32 i;
	if(p)			// i[̃|C^NULLłȂ
	{
		p[*index] = attr;	// ^O(4(String)6(OID))Zbg
		p[*index + 1] = size;	// ̒Zbg
		for(i = 0; i < size; i++)	//@1i[郋[v
			p[*index + 2 + i] = *data++;	// 1i[
	}
	(*index) += size + 2;		// i[CfbNX𕶎̒{2i߂
}

//
//	lGgi[
//
void SetNumber(UINT8 *p, UINT8 attr, UINT32 *index, UINT32 data)
{
	if(p)				// i[̃|C^NULLłȂ
		p[*index] = attr;	// l^Oi[
	if(data & 0xff800000)		// l4oCg͈̔͂H
	{
		if(p)			// i[̃|C^NULLłȂ
		{
			p[*index + 1] = 4;	// 4oCg̒Zbg
			*(UINT8*)&p[*index + 2] = (UINT8)(data >> 24);	// 1oCgi[
			*(UINT8*)&p[*index + 3] = (UINT8)(data >> 16);	// 2oCgi[
			*(UINT8*)&p[*index + 4] = (UINT8)(data >> 8);	// 3oCgi[
			*(UINT8*)&p[*index + 5] = (UINT8)data;	// 4oCgi[
		}
		(*index) += 6;		// CfbNX6i߂
	}
	else if(data & 0xff8000)	// l3oCg͈̔͂H
	{
		if(p)			// i[̃|C^NULLłȂ
		{
			p[*index + 1] = 3;	// 3oCg̒Zbg
			*(UINT8*)&p[*index + 2] = (UINT8)(data >> 16);	// 1oCgi[
			*(UINT8*)&p[*index + 3] = (UINT8)(data >> 8);	// 2oCgi[
			*(UINT8*)&p[*index + 4] = (UINT8)data;	// 3oCgi[
		}
		(*index) += 5;		// CfbNX5i߂
	}
	else if(data & 0xff80)		// l2oCg͈̔͂H
	{
		if(p)			// i[̃|C^NULLłȂ
		{
			p[*index + 1] = 2;	// 2oCg̒Zbg
			*(UINT8*)&p[*index + 2] = (UINT8)(data >> 8);	// 1oCgi[
			*(UINT8*)&p[*index + 3] = (UINT8)data;	// 2oCgi[
		}
		(*index) += 4;		// CfbNX4i߂
	}
	else				// l1oCg͈̔͂̂͂
	{
		if(p)			// i[̃|C^NULLłȂ
		{
			p[*index + 1] = 1;	// 1oCg̒Zbg
			*(UINT8*)&p[*index + 2] = (UINT8)data;	// 1oCgi[
		}
		(*index) += 3;		// CfbNX3i߂
	}
}

//
//	Gg̒𓾂
//
UINT32 GetValueLen(UINT8 attr, UINT8 *val)
{
	switch(attr)	// ɂď𕪂
	{
	case 4:		// Ȃ
		return (UINT8)StrLen((INT8*)val);	// ̒ċA
		break;
	case 5:		// NULLGgȂ
		return 0;	// 0
		break;
	case 2:		// H
	case 0x40:	// IPAhXH
	case 0x43:	// TIMETICKH
	case 0x41:	// COUNTERH
		if(*(UINT32*)val & 0xff800000)	// 4oCgɎ܂邩H
			return 4;	// 4
		else if(*(UINT32*)val & 0xff8000)// 3oCgɎ܂邩H
			return 3;	// 3
		else if(*(UINT32*)val & 0xff80)	// 2oCgɎ܂邩H
			return 2;	// 2
		else			// 1oCg̐l̂͂
			return 1;	// 1
		break;
	}
	return 0;	// 悭킩ȂȂ0ċA
}

//
//	SNMP̃X|XpPbg쐬
//
UINT32 MakeReplyPacket(UINT8 *p, OidTable *oidtbl, UINT8 mn, UINT8 cmd, INT32 id, UINT16 size)
{
UINT32	i, j, len, index;
UINT8*	temp;
	index = 0;					// i[CfbNX擪ɃZbg
	StoreSub(p, &index, 0x30); 			// z^OZbg  
	StoreLength(p, &index, size - index - 3); 	// Ŝ̒Zbg
	SetNumber(p, 2, &index, 0);			// SNMPo[WZbg(V1Ȃ̂0ASNMP̂)	
	if(IdNumber)					// foCXIDw肳Ă
	{
		temp = (UINT8*)MemoryAlloc((UINT8)StrLen(Community) + 5 + 1);	// R~jeB{i[ꎞ̈m
		sprintf((INT8*)temp, "%s%d", Community, IdNumber);	// R~jeB{쐬i[
		SetString(p, &index, 4, temp, (UINT8)StrLen(temp));	// Ggi[	
		MemoryFree(temp);					// ꎞ̈J
	}
	else						// foCXID̎w肪
		SetString(p, &index, 4, Community, (UINT8)StrLen(Community));// PɃR~jeBi[	
	StoreSub(p, &index, cmd);			// GetResponseR}h(0xa2)Zbg  
	StoreLength(p, &index, size - index - 3);	// Zbg
	SetNumber(p, 2, &index, id);			// RequestŎw肳ꂽAԂRs[
	SetNumber(p, 2, &index, 0);			// G[R[h0Zbg(SNMP̂)
	SetNumber(p, 2, &index, 0);			// G[CfbNX0Zbg(SNMP̂)
	StoreSub(p, &index, 0x30);			// z^OZbg  
	StoreLength(p, &index, size - index - 3);	// Zbg
	for(i = 0; i < mn; i++)				// w肳ꂽOID̃XgԂɊi[郋[v
	{	// OID̒ƃGg̒̍v\ߌvZĂ
		len = (oidtbl + i)->namelen + 4 + GetValueLen((UINT8)(oidtbl + i)->valattr, (oidtbl + i)->value);
		StoreSub(p, &index, 0x30); 		// z(̃Gg̘Azu)^OZbg
		StoreSub(p, &index, (UINT8)len); 	// Zbg
		SetString(p, &index, 6, (oidtbl + i)->name, (UINT8)(oidtbl + i)->namelen);// OIDi[
		switch((oidtbl + i)->valattr)		// Ήl̑ɂ蕪
		{
		case 4:					// 񂩁H
			StoreSub(p, &index, 4); 	// ^Oi[  
			len = (UINT8)StrLen((oidtbl + i)->value);	// ̒𓾂
			StoreSub(p, &index, (UINT8)len);// i[  
			for(j = 0; j < len; j++)	// 1i[郋[v
				StoreSub(p, &index, (oidtbl + i)->value[j]);// 1i[Ă
			break;
		case 5:					// NULLGgH
			StoreSub(p, &index, 5); 	// NULL^O(5)Zbg
			StoreSub(p, &index, 0); 	// (0)Zbg
			break;
		case 2:					// lH
		case 0x40:				// IPAhXH
		case 0x43:				// TIMETICKH
		case 0x41:				// COUNTERHȂ琔li[
			SetNumber(p, (UINT8)(oidtbl + i)->valattr, &index, *(UINT32*)(oidtbl + i)->value);
			break;
		}
	}
	return index;	// Ŝ̒ċA
}

//
//	OIDLbVɃf[^o^EXV
//
UINT8 RegisterOidCache(OidTable *oidtbl, UINT32 num, UINT32 r)
{
UINT32	i, j, k, l, idnum;
UINT8		*oid;
INT32		sd[4];	// 4ch̃f[^pobt@
	idnum = 0;	// foCXIDNAĂ
	for(i = 0; i < 4; i++)
		sd[i] = 0x7fff;	// 4ch̃f[^2oCg̍őlɃNAĂ
	if(oidtbl == NULL)	// LbVe[ũ|C^ƂNULLw肳ꂽH
	{		// LbṼtbVsԂoLbV͏
		if(num)	// Ԃw肳Ă邩?
		{				// ÂLbV̏Jn
			for(i = 1; i < MaxCache; i++)	// ŏ̃_~[R[hɂ͐GȂ
			{			// ׂẴLbV`FbN郋[v
				if((OidCache + i)->Id)	// LȃR[hH
				{
					if((OidCache + i)->life > num)	// ƔrĂ݂
						(OidCache + i)->life -= num;	// cĂΎ炷
					else		// LbV̎s
						MemClear(OidCache + i, sizeof(OidCache_t));	// R[h
				}
			}
		}
		else		// LbVe[ũ|C^NULLŎԂ̎wꍇ
		{		// LbV̊mۂƏ̏sȂ
			OidCache = (OidCache_t*)MemoryAlloc(sizeof(OidCache_t) * MaxCache);	// OIDLbV̗̈m
			MemClear(OidCache, sizeof(OidCache_t) * MaxCache);	// OIDLbVNA
			OidCache->Id = 1;	// 擪Ƀ_~[f[^i[(ID=1)
			OidCache->life = 600;	// _~[̎Zbg(ۂɂ͉Ă֌WȂ)
		}
	}
	else		// OIDLbṼ|C^w肳Ăꍇ
	{		// f[^̎o[h
		if(r)	// foCXIDw肳Ă邩HȂΎo[h
		{
			for(i = 1; i < MaxCache; i++)		// SOIDR[hXL
				if((OidCache + i)->Id == r)	// w肳ꂽfoCXIDƃ}b`
					break;			// XL[v𔲂
			if(i == MaxCache)			// R[hH
					return 1;		// Ȃ1ċA
			r = i;					// 烌R[h̃CfbNXۑ
			for(i = 0; i < num; i++)		// w肳ꂽOIDe[u̐JԂ
			{
				for(j = 0; j < OIDTABLECOUNT; j++)	// gݍݍςOIDe[uƏƂ炵킹
				{
					k = ParseOidStr((UINT8*)InitOidList[j], &oid);	// gݍݍςOIDe[uOIDGg𓾂
					if(k)	// ɕϊłȂOIDGg̒kɕێ
					{	// w肳ꂽOIDGgƔr
						l = 0;	// rCfbNXNA
						if(k == (oidtbl + i)->namelen)	// ҂OIDGg̒vĂȂ
							for(;l < k; l++)	// 1oCgׂĔr
								if((oidtbl + i)->name[l] != oid[l])	// ႵĂ
									break;	// r[v𔲂
						MemoryFree(oid);	// gݍݍςOIDGg̈ꎞ̈J
						if(l == k)	// Ō܂ňvH
						{	// w肳ꂽOIDGg͑gݍݍς݂OIDƈv̂
							MemoryFree((oidtbl + i)->value);	// ݂̃f[^̈J
							(oidtbl + i)->value = (UINT8*)MemoryAlloc(4);	// V4oCg̗̈m
							*(UINT32*)(oidtbl + i)->value = 0;	// mۂ̈NA
							(oidtbl + i)->valattr = 2;		// (2)i[
							if(j != IDINDEX)	// f[^OIDȂ΃LbVlo
							{
								k = (OidCache + r)->Data[j - DATASTART];	// LbVf[^𓾂
								if(k != 0x7fff)	// f[^1xłZbgĂ邩H
									*(INT32*)(oidtbl + i)->value = k;	// Ȃf[^擾
								else
									(oidtbl + i)->valattr = 5;	// xZbgĂȂȂNULL^OZbg
							}
							break;	// gݍݍςOIDe[uƂ̈vo[vo
						}	// if(l == k)̖
					}	// if(k)̖
				}	// gݍݍςOIDe[uƂ̈vo[v̖
			}	// ^ꂽOIDe[uJԂ
		}	// f[^̎o[h̖
		else
		{	// foCXIDw肳ĂȂΓo^[h
			for(i = 0; i < num; i++)	// ^ꂽOIDe[ũf[^ׂĂɑ΂ČJԂ
			{
				for(j = 0; j < OIDTABLECOUNT; j++)	// gݍݍςOIDe[uƏƂ炵킹
				{
					k = ParseOidStr((UINT8*)InitOidList[j], &oid);	// gݍݍςOIDe[uOIDGg𓾂
					if(k)	// ɕϊłȂOIDGg̒kɕێ
					{
						l = 0;	// rCfbNXNA
						if(k == (oidtbl + i)->namelen)	// ҂OIDGg̒vĂ
							for(;l < k; l++)	// 1oCgׂĔr郋[v
								if((oidtbl + i)->name[l] != oid[l])	// ႵĂ
									break;	// [v𔲂
						MemoryFree(oid);	// gݍݍςOIDGg̈ꎞ̈J
						if(l == k)	// Ō܂ňvH
						{
							switch(j)	// ꂽOID̓foCXIDf[^ɂ蕪
							{
							case IDINDEX:	// ^ꂽ̂̓foCXIDȂ
								idnum = *(UINT32*)(oidtbl + i)->value;	// foCXIDidnumɕۑ
								break;
							default:
								if((oidtbl + i)->valattr != 0x05)	// f[^OIDȂ
									sd[j - DATASTART] = *(INT32*)(oidtbl + i)->value;// f[^pobt@ɕۑ
							}
							break;	// gݍݍςOIDe[uƂ̈vo[vo
						}
					}			// if(k)̖
				}				// gݍݍςOIDe[ũ[v̖
			}					// ^ꂽOIDe[ũXL[v̖
			if(idnum == 0)				// OIDXg̒ɃfoCXIDw肳ĂȂꍇ
				return 1;			// foCXIDȂΓo^s\Ȃ̂ŃG[ŋA
			for(i = 1; i < MaxCache; i++)		// OIDLbVׂă`FbN
				if((OidCache + i)->Id == idnum)	// foCXID̃R[h݂邩H
					break;			// ݂烋[v𔲂
			if(i == MaxCache)			// foCXID݂Ȃ
			{	// VR[hƂēo^
				for(i = 1; i < MaxCache; i++)	// 󂢂Ăe[u郋[v
					if((OidCache + i)->Id == 0)	// 󂢂Ăe[u𔭌
						break;		// 󂫃e[u[v𔲂
				if(i == MaxCache)		// c͂ȂH
					return 1;		// ȏo^oȂ̂ŃG[^[
				(OidCache + i)->Id = idnum;	// VKɃfoCXIDo^
			}
			for(j = 0; j < 4; j++)	// VKłXVłf[^4chׂēo^
				(OidCache + i)->Data[j] = sd[j];	// LbVɃf[^i[
			(OidCache + i)->life = 600;		// 10̃LbVݒ肷
		}
	}
	return 0;	// ̂0ċA
}

//
//	SNMPpPbg郁C[v
//
void SnmpHandler(void)
{
UINT32	i, j, mnum, cmd, err;
UINT32	len, sockinfo_len, buf_len, request;
UINT8		*buf, *p, *q, *comtemp;
SOCKET	soc;					// \Pbg
OidTable *oidtbl;				// OIDXg̃|C^
struct  sockaddr_in	 sockinfo;		// \Pbg(MAhX擾p)
time_t	time1, time2;				// Time\(p)
	RegisterOidCache(NULL, 0, 0);		// ܂OIDLbVė̈mۂ
	soc = socket(PF_INET, SOCK_DGRAM, 0);	// UDPǂƂ𐶐
	if(soc == INVALID_SOCKET)		// \PbgɎs
	{
		fprintf(stderr, "Fail to create socket\n");	// G[bZ[Wo
		MemoryFree(OidCache);		// OIDLbV̗̈J
		return;				// mainɖ߂
	}
	memset(&sockinfo, 0, sizeof(sockinfo));	// \PbgNA
	sockinfo.sin_family = AF_INET;		// C^[lbgAhXgp
	sockinfo.sin_addr.s_addr = htonl(INADDR_ANY);	// ׂĂIPAhX̎M
	sockinfo.sin_port = htons(SnmpPort);	// SNMP҂|[gԍ(161)ݒ
	buf_len = bind(soc, (struct sockaddr *)&sockinfo, sizeof(sockinfo));	// UDP\Pbgɑ҂|[gԍݒ
	if(buf_len == SOCKET_ERROR)		// Ȃɂ̃G[H
	{
		fprintf(stderr, "Fail to bind listening port(%d)\n", SnmpPort);// G[\
		MemoryFree(OidCache);		// OIDLbV̗̈J
		return;				// mainɖ߂
	}
	buf = (UINT8*)MemoryAlloc(2048);	// pPbgMp̃obt@̈m({1500oCgŗǂ)
	time(&time1);				// ݎ擾
	for(;;)					// SNMPnh̃C[vJn
	{
		sockinfo.sin_addr.s_addr = INADDR_ANY;	// ׂĂIPAhX̎M
		sockinfo_len = sizeof(sockinfo);	// \Pbg\̂̒𓾂
		len = recvfrom(soc, (INT8*)buf, 1500, 0, (struct sockaddr *)&sockinfo, (int *)&sockinfo_len);	// UDPpPbgM܂ő҂
		DebugPrint("Recieved\n");	// fobOpvg
		if(len > 32 && len != SOCKET_ERROR)	// G[MH
		{
			IdNumber = 0;	// foCXIDNA
			mnum = 0;	// OIDXg̐NA
			p = buf;	// Mobt@̃Rs[pɊi[
			oidtbl = NULL;	// OIDXg̃|C^NAĂ
			err = 1;	// ܂G[tO𗧂ĂĂ
			for(;;)		// _~[for[v(ۂɂ̓[vG[breakŔׂɎgp)
			{
				if(*p++ != 0x30)	// 擪͔z^O0x30?
					break;		// łȂ΃G[
				if(GetElementLen(&p) != len - (p - buf))	// Ŝ̒`FbN
					break;		// Ⴊ΃G[
				if(GetInteger(&p) != 0)	// SNMP@V1ǂ`FbN
					break;		// łȂ΃G[
				comtemp = GetString(&p);// R~jeB擾								
				if(comtemp == NULL)	// R~jeB?
					break;		// ȂG[
				i = (UINT32)StrLen(Community);	// ƍp̃R~jeB̒擾
				j = (UINT32)StrLen(comtemp);	// ^ꂽR~jeB̒擾
				if(j > i)	// ^ꂽR~jeB
					j = ParseNum(comtemp + i);	// ̐͂
				else
					j = -1;			// ԍw肳ĂȂ̂ŃfoCXIDƂ-1ZbgĂ
				if(StrNcmp(comtemp, Community, i))	// R~jeBr
				{	// }b`ȂȂ
					MemoryFree(comtemp);	// ^ꂽR~jeB̈ꎞ̈J
					break;			// R~jeBsvȂ̂ŃG[
				}
				MemoryFree(comtemp);		// ^ꂽR~jeB̈ꎞ̈J
				cmd = *p++;			// ^ꂽSNMPR}h擾
				if(cmd < 0xa0 || cmd > 0xa8)	// SetRequest܂GetRequest
					break;			// łȂ΃G[
				if(GetElementLen(&p) != len - (p - buf))	// ēx`FbN
					break;			// sȂG[
				request = GetInteger(&p);	// pPbgAԂ擾
				if(request == -1)		// lł͂ȂH 
					break;			// lłȂ΃G[
				if(GetInteger(&p) == -1)	// G[R[h`FbN
					break;			// łȂ΃G[
				if(GetInteger(&p) == -1)	// G[CfbNX`FbN
					break;			// łȂ΃G[
				if(*p++ != 0x30)		// z^O(0x30)?
					break;			// łȂ΃G[
				if(GetElementLen(&p) != len - (p - buf))// ܂܂`FbN
					break;			// sȂG[
				q = p;				// ݂̓ǂݍ݃|C^ۑ
				for(;;)				// 񋓂ĂOIDƃf[^̃yAׂĉ͂
				{
					if(q == buf + len)	// Ō܂ŉ͂H
						break;		// OID̓[v𔲂
					if(GetOidData(&q, NULL))// OIDƃf[^̃yAǂݔ΂
						break;		// ȂɂG[Ή̓[v𔲂
					mnum++;			// OID̃ACeZ
				}
				if(mnum == 0)			// OID܂܂ĂȂȂH
					break;			// G[Ŕ
				oidtbl = (OidTable*)MemoryAlloc(mnum * sizeof(OidTable));// OIDꎞe[üm
				MemClear((UINT8*)oidtbl, mnum * sizeof(OidTable));	// OIDꎞe[uŜNA
				for(i = 0; i < mnum; i++)	// w肳ĂOID̐JԂ
					(void)GetOidData(&p, oidtbl + i);	// OIDƒl̃yAOIDꎞe[uɊi[Ă
				err = 0;			// 󂯎pPbgɃG[͖̂ŃG[tONA
				break;				// ĐIƂfor(;;)[v𔲂
			}
			if(err == 0)					// G[tONAĂ邩H
			{						// 󂯎pPbg͐SNMPpPbĝ
				if(cmd == 0xa3)				// 󂯎pPbgSetRequestpPbg?
				{					// Ȃf[^o^
					DebugPrint("Set\n");		// fobOpvg
					if(RegisterOidCache(oidtbl, (UINT8)mnum, 0))	// OIDLbVɎ󂯎f[^o^
						cmd = 0;		// o^łȂcmdNAăpPbgԑh
				}
				else if(cmd == 0xa0)			// 󂯎pPbgGetRequest?
				{					// ȂOIDLbVf[^o
					DebugPrint("Get\n");		// fobOpvg
					if(j != -1)			// foCXIDw肳Ă
						IdNumber = (UINT16)j;	// foCXIDۑ
					if(RegisterOidCache(oidtbl, (UINT8)mnum, j))	// OIDLbVw肵foCXID̃f[^擾
						cmd = 0;		// G[ȂcmdNAĕԑȂ
				}
				if(cmd == 0xa0 || cmd == 0xa1 || cmd == 0xa3)	// GetRequestGetNextRequestSetRequestȂ?
				{						// Ԏ̃pPbgԑKv
					len = MakeReplyPacket(NULL, oidtbl, (UINT8)mnum, 0xa2, request, 0);	// ܂ԑpPbg̒𒲂ׂ
					if(len < 0x200)				// pPbg̃TCY512ȉȂ琳
					{					// ۂɗ̈mۂSNMPpPbg쐬
						q = (UINT8*)MemoryAlloc(len);	// KvȃTCỸobt@̈m
						if(!q)	// mۂɎsH
						{
							fprintf(stderr, "Fail to allocate buffer\n");	// fobOpvg
							MemoryFree(OidCache);	// OIDLbV̗̈J
							return;			// G[^[
						}
						len = MakeReplyPacket(q, oidtbl, (UINT8)mnum, 0xa2, request, (UINT16)len);// SNMPpPbgۂɍ쐬
						if(sendto(soc, (INT8*)q, len, 0, (struct sockaddr *)&sockinfo, sizeof(sockinfo)) == SOCKET_ERROR)// UDPM
						{	// MɎs
							fprintf(stderr, "Fail to send UDP data\n");	// fobOpvg
							MemoryFree(q);		// SNMPpPbgobt@J
							MemoryFree(OidCache);	// OIDLbV̗̈J
							return;			// G[^[
						}
						DebugPrint("Sent\n");	// fobOpvg
						MemoryFree(q);		// SNMPpPbgobt@J
					}
				}
			}
			for(i = 0; i < mnum; i++)	// OIDXg̐JԂ[v
			{				// 쐬OIDXgŎgpJ
				MemoryFree((oidtbl + i)->name);	// OIDJ
				MemoryFree((oidtbl + i)->value);// l̃obt@J
			}
			MemoryFree(oidtbl);		// OIDXg̃J
		}
		time(&time2);				// ݎ𓾂
		i = (INT32)difftime(time2, time1);	// O擾Ƃ̍߂
		if(i > 10)				// O10bȏo߂H
		{					// ȂOIDLbVtbV
			time1 = time2;			// ݎۑ
			RegisterOidCache(NULL, i, 0);	// OIDLbVXLČÂR[h
		}
	}
}

//
//	C
//
int main(UINT32 argc, INT8 *argv[])
{
#ifdef	WIN32		// Windows
WSADATA wsaData;	// Winsockp̕ϐKv
#endif
//	ϐ̏BR}hIvVŕύXł悤ɉĂǂ
	SnmpPort = 161;	// ftHgSNMP|[gԍ
	Community = (UINT8*)"public";	// ftHg̃R~jeB
	MaxCache = OIDBUFSIZE;		// ő1024̈قȂfoCXID܂őΉ
#ifdef	WIN32		// Windows
	WSAStartup(2 , &wsaData);	// WinSock̏Kv
#endif	
	SnmpHandler();	// C[vĂяo
#ifdef	WIN32		// Windows
	WSACleanup();	// WinSock̏IKv
#endif
	return 0;	// C̏I
}

