/*****************************************************************************/ /* HTTP2watch.c VERSION HISTORY --------------- 14-FEB-2019 MGD Http2WatchFrame() relax WATCH from module to regular 17-AUG-2015 MGD initial */ /*****************************************************************************/ #ifdef WASD_VMS_V7 # undef __VMS_VER # define __VMS_VER 70000000 # undef __CRTL_VER # define __CRTL_VER 70000000 #else # ifdef WASD_VMS_V7 # undef _VMS__V6__SOURCE # define _VMS__V6__SOURCE # undef __VMS_VER # define __VMS_VER 70000000 # undef __CRTL_VER # define __CRTL_VER 70000000 # endif #endif #include #include #include "wasd.h" #define WASD_MODULE "HTTP2WATCH" /******************/ /* global storage */ /******************/ /********************/ /* external storage */ /********************/ extern char *Http2ErrorArray []; extern WATCH_STRUCT Watch; /*****************************************************************************/ /* */ void Http2WatchFrame ( HTTP2_STRUCT *h2ptr, uchar *FramePtr, uchar *DataPtr, uint BufferLength, BOOL magic ) { uint flags, flen, ident, type; uchar *csptr, *fptr, *tptr; char flstr [64]; /*********/ /* begin */ /*********/ if (WATCHMOD (h2ptr, WATCH_MOD_HTTP2)) WatchThis (WATCHITM(h2ptr), WATCH_MOD_HTTP2, "Http2WatchFrame()"); fptr = FramePtr; HTTP2_GET_24 (fptr, flen); HTTP2_GET_8 (fptr, type); HTTP2_GET_8 (fptr, flags); HTTP2_GET_32 (fptr, ident); flstr[0] = '\0'; switch (type) { case HTTP2_FRAME_DATA : if (magic) tptr = "DATA (magic)"; else tptr = "DATA"; if (flags & HTTP2_FLAG_DATA_END_STR) strcat (flstr, " END-STREAM"); if (flags & HTTP2_FLAG_DATA_PADDED) strcat (flstr, " PADDED"); if (flags & ~(HTTP2_FLAG_DATA_END_STR | HTTP2_FLAG_DATA_PADDED)) strcat (flstr, " ?"); break; case HTTP2_FRAME_HEADERS : tptr = "HEADERS"; if (flags & HTTP2_FLAG_HEAD_END_STR) strcat (flstr, " END-STREAM"); if (flags & HTTP2_FLAG_HEAD_END_HEAD) strcat (flstr, " END-HEADERS"); if (flags & HTTP2_FLAG_HEAD_PADDED) strcat (flstr, " PADDED"); if (flags & HTTP2_FLAG_HEAD_PRIORITY) strcat (flstr, " PRIORITY"); if (flags & ~(HTTP2_FLAG_HEAD_END_STR | HTTP2_FLAG_HEAD_END_HEAD | HTTP2_FLAG_HEAD_PADDED | HTTP2_FLAG_HEAD_PRIORITY)) strcat (flstr, " ?"); break; case HTTP2_FRAME_PRIORITY : tptr = "PRIORITY"; break; case HTTP2_FRAME_RST_STREAM : tptr = "RST_STREAM"; break; case HTTP2_FRAME_SETTINGS : tptr = "SETTINGS"; if (flags & HTTP2_FLAG_SETTINGS_ACK) strcat (flstr, " ACKNOWLEDGE"); if (flags & ~HTTP2_FLAG_PING_ACK) strcat (flstr, " ?"); break; case HTTP2_FRAME_PUSH_PROMISE : tptr = "PUSH_PROMISE"; if (flags & HTTP2_FLAG_PUSH_END_HEAD) strcat (flstr, " END-HEADERS"); if (flags & HTTP2_FLAG_PUSH_PADDED) strcat (flstr, " PADDED"); if (flags & ~(HTTP2_FLAG_PUSH_END_HEAD | HTTP2_FLAG_PUSH_PADDED)) strcat (flstr, " ?"); break; case HTTP2_FRAME_PING : tptr = "PING"; if (flags & HTTP2_FLAG_PING_ACK) strcat (flstr, " ACKNOWLEDGE"); if (flags & ~HTTP2_FLAG_PING_ACK) strcat (flstr, " ?"); break; case HTTP2_FRAME_GOAWAY : tptr = "GOAWAY"; break; case HTTP2_FRAME_WINDOW_UPDATE : tptr = "WINDOW_UPDATE"; break; case HTTP2_FRAME_CONTINUATION : tptr = "CONTINUATION"; if (flags & HTTP2_FLAG_HEAD_END_HEAD) strcat (flstr, " END-HEADERS"); if (flags & ~HTTP2_FLAG_HEAD_END_HEAD) strcat (flstr, " ?"); break; default : tptr = "?"; } if (flags && !flstr[0]) strcpy (flstr, " ?"); if (FramePtr >= h2ptr->ReadBufferPtr && FramePtr < h2ptr->ReadBufferPtr + h2ptr->ReadBufferSize) csptr = "client"; else csptr = "server"; WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "FRAME !AZ length:!UL type:!UL !AZ flags:0x!2XL!AZ ident:!UL", csptr, flen, type, tptr, flags, flstr, ident); switch (type) { case HTTP2_FRAME_DATA : if (DataPtr) fptr = DataPtr; if (WATCHMOD (h2ptr, WATCH_MOD_HTTP2)) Http2WatchData (h2ptr, ident, flags, fptr, flen, BufferLength); break; case HTTP2_FRAME_HEADERS : case HTTP2_FRAME_CONTINUATION : Http2WatchHeaders (h2ptr, ident, flags, fptr, flen, BufferLength); break; case HTTP2_FRAME_PRIORITY : Http2WatchPriority (h2ptr, ident, fptr, flen); break; case HTTP2_FRAME_RST_STREAM : Http2WatchRstStream (h2ptr, ident, fptr, flen); break; case HTTP2_FRAME_SETTINGS : Http2WatchSettings (h2ptr, csptr, fptr, flen); break; case HTTP2_FRAME_PUSH_PROMISE : Http2WatchPushPromise (h2ptr, ident, flags, fptr, flen); break; case HTTP2_FRAME_PING : Http2WatchPing (h2ptr, fptr, flen); break; case HTTP2_FRAME_GOAWAY : Http2WatchGoAway (h2ptr, fptr, flen); break; case HTTP2_FRAME_WINDOW_UPDATE : Http2WatchWindowUpdate (h2ptr, ident, fptr, flen); break; default : WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "FRAME error!"); } } /*****************************************************************************/ /* */ void Http2WatchData ( HTTP2_STRUCT *h2ptr, uint ident, uint flags, uchar *fptr, uint flen, uint blen ) { uint padlen; /*********/ /* begin */ /*********/ if (WATCHMOD (h2ptr, WATCH_MOD_HTTP2)) { if (flags & HTTP2_FLAG_DATA_PADDED) HTTP2_GET_8 (fptr, padlen) else padlen = 0; WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "DATA padding:!UL length:!UL", padlen, flen - padlen); /* dump only as many bytes as we have */ /// WatchDataDump (fptr, blen >= flen - padlen ? flen - padlen : blen); } } /*****************************************************************************/ /* */ void Http2WatchGoAway ( HTTP2_STRUCT *h2ptr, uchar *fptr, uint flen ) { uint addlen, lastid, error; /*********/ /* begin */ /*********/ HTTP2_GET_32 (fptr, lastid); lastid &= 0x7fffffff; HTTP2_GET_32 (fptr, error); addlen = flen - sizeof(uint) - sizeof(uint); WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "GOAWAY lastident:!UL error:!UL \"!AZ\"!AZ!#AZ!AZ", lastid, error, Http2ErrorString(error), addlen ? " \"" : "", addlen, fptr, addlen ? "\"" : ""); } /*****************************************************************************/ /* */ void Http2WatchHeaders ( HTTP2_STRUCT *h2ptr, uint ident, uint flags, uchar *fptr, uint flen, uint blen ) { uint hbflen, padlen, depend, weight; uchar *bptr; /*********/ /* begin */ /*********/ if (WATCHMOD (h2ptr, WATCH_MOD_HTTP2)) { bptr = fptr; if (flags & HTTP2_FLAG_HEAD_PADDED) HTTP2_GET_8 (fptr, padlen) else padlen = 0; if (flags & HTTP2_FLAG_HEAD_PRIORITY) { HTTP2_GET_32 (fptr, depend) HTTP2_GET_8 (fptr, weight) } else depend = weight = 0; WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "HEADERS str:!&B end:!&B pad:!&B prio:!&B \ padding:!UL depend:!UL (ex:!&B) header:!UL (!UL)", flags & HTTP2_FLAG_HEAD_END_STR, flags & HTTP2_FLAG_HEAD_END_HEAD, flags & HTTP2_FLAG_HEAD_PADDED, flags & HTTP2_FLAG_HEAD_PRIORITY, padlen, depend, depend & 0x80000000, flen - padlen, blen); /* dump only as many bytes as we have */ WatchDataDump (fptr, blen >= flen - padlen ? flen - padlen : blen); } } /*****************************************************************************/ /* */ void Http2WatchPing ( HTTP2_STRUCT *h2ptr, uchar *fptr, uint flen ) { /*********/ /* begin */ /*********/ if (WATCHMOD (h2ptr, WATCH_MOD_HTTP2)) WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "PING !2XL!2XL!2XL!2XL!2XL!2XL!2XL!2XL", fptr[0],fptr[1],fptr[2],fptr[3], fptr[4],fptr[5],fptr[6],fptr[7]); } /*****************************************************************************/ /* */ void Http2WatchPriority ( HTTP2_STRUCT *h2ptr, uint ident, uchar *fptr, uint flen ) { uint depend, weight; /*********/ /* begin */ /*********/ HTTP2_GET_32 (fptr, depend) HTTP2_GET_8 (fptr, weight) WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "PRIORITY depend:!UL (ex:!UL) weight:!UL", depend & 0x7fffffff, depend & 0x80000000, weight+1); } /*****************************************************************************/ /* */ void Http2WatchPushPromise ( HTTP2_STRUCT *h2ptr, uint ident, uint flags, uchar *fptr, uint flen ) { uint hbflen, padlen, promid; /*********/ /* begin */ /*********/ if (flags & HTTP2_FLAG_DATA_PADDED) HTTP2_GET_8 (fptr, padlen) else padlen = 0; HTTP2_GET_32 (fptr, promid); promid &= 0x7fffffff; hbflen = flen - sizeof(uchar) - sizeof(uint) - sizeof(uchar) - padlen; WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "PUSH_PROMISE padding:!UL promid:!UL header:!UL", padlen, promid, hbflen); if (WATCHMOD (h2ptr, WATCH_MOD_HTTP2)) WatchData (fptr, hbflen); } /*****************************************************************************/ /* */ void Http2WatchRstStream ( HTTP2_STRUCT *h2ptr, uint ident, uchar *fptr, uint flen ) { uint error; /*********/ /* begin */ /*********/ HTTP2_GET_32 (fptr, error); WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "RST_STREAM ident:!UL error:!UL \"!AZ\"", ident, error, Http2ErrorString(error)); } /*****************************************************************************/ /* */ void Http2WatchSettings ( HTTP2_STRUCT *h2ptr, uchar *csptr, uchar *fptr, uint flen ) { uint setting, value; char *cptr; /*********/ /* begin */ /*********/ for (;(int)flen >= 6; flen -= 6) { HTTP2_GET_16 (fptr, setting); HTTP2_GET_32 (fptr, value); switch (setting) { case HTTP2_SETTING_MAX_HEAD_TABLE_SIZE : cptr = "header table size"; break; case HTTP2_SETTING_ENABLE_PUSH : cptr = "server push enabled"; break; case HTTP2_SETTING_MAX_CONC_STREAMS : cptr = "max concurrent streams"; break; case HTTP2_SETTING_INIT_WIN_SIZE : cptr = "initial window size"; break; case HTTP2_SETTING_MAX_FRAME_SIZE : cptr = "max frame size"; break; case HTTP2_SETTING_MAX_HEAD_LIST_SIZE : cptr = "max header list size"; break; default : cptr = "(unknown)"; } WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "SETTING !AZ !AZ: !UL", csptr, cptr, value); } if (flen) WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "SETTING error!!"); } /*****************************************************************************/ /* */ void Http2WatchWindowUpdate ( HTTP2_STRUCT *h2ptr, uint ident, uchar *fptr, uint flen ) { uint value; /*********/ /* begin */ /*********/ HTTP2_GET_32 (fptr, value); value &= 0x7fffffff; WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "WINDOW_UPDATE ident:!UL value:!UL", ident, value); } /*****************************************************************************/ /* */ void Http2WatchError ( HTTP2_STRUCT *h2ptr, uint error ) { char *sptr; /*********/ /* begin */ /*********/ if (error < HTTP2_ERROR_COUNT) sptr = Http2ErrorArray[error]; else sptr = "?"; WatchThis (WATCHITM(h2ptr), WATCH_HTTP2, "ERROR !UL !AZ", error, sptr); } /*****************************************************************************/